一、面向对象-OOD
虽然js面向对象的编程思想已经老话常谈了,但了为了文章的完整性,我还是把它加了进来,尽量以不太一样的方式讲述(虽然也没什么卵不一样的)。
1、面向对象,首先得有类的概念,没有类造不出来对象,但是javascript中又没有类 只有函数的感念,把以大写字母命名的函数看成创建对象的构造函数,把函数名看成类,那么就可以new一个对象了
1 //1.1 无参的 2 function People() { 3 4 } 5 var p = new People(); 6 //javascript为解释性语言,运行时编译,所以我们点什么属性,就会有什么属性了。 7 p.name = 'hannimei'; 8 console.log(p.name); 9 //2.2 来个有参数的 10 function Student(name, age) { 11 this.name = name; 12 this.age = age; 13 this.say = function () { 14 return saywhat(); 15 }<br> //私有函数<br> function saywhat(){<br> return this.name+':say what?';<br> } 16 return this; 17 } 18 var s = new Student('lily', 18); 19 console.log(s.name); 20 console.log(s.say()); 21 //2.3 来个factory 22 function Factory(name,age) { 23 var obj = new Object(); 24 obj.name = name; 25 obj.age = age; 26 obj.say = function () { 27 return obj.name+ ':say what?'; 28 } 29 return obj; 30 } 31 var o = new Factory('factory', 1); 32 console.log(o.say()); 33 34 //2.4对象字面方式创建对象 35 var ob = { Name: "字面量", Age: 18 }; 36 //当然也有字符串字面量、数组字面量这些 37 var str = 'hello javascript!'; 38 var arr = [1, 2, 3, 4, 5];
2、那么有了类,面向对象同样不能少的特性就是继承;js中继承有各种方式的实现,通过函数原型链最常见不过了
天生自带技能乃是命,如果后来想修炼技能怎么办,直接点出来就好了嘛;如果不想修炼就想天生自带,那就得说下prototype了。
1 function Teacher(schoolname) { 2 this.schoolname = schoolname; 3 return this; 4 } 5 var t = new Teacher('2b1中');
创建Teacher函数对象t时,t的__proto__指向了一个object,这个的指向其实就是函数的原型(为什么呢?听我慢慢往下道),如图:这 个object又有两个属性,constructor定义了创建它的Teacher函数,__proto__继续向上指向Object,通过这种对象二叉 树的结构,就标识了这个对象怎么来的和出生都自带什么技能。
那我们后台想自带技能就要通过增加t的__proto__指向的那个object默认技能了
从Teacher的监视图我们看到两个关键的属性,一个是它的函数原型prototype,测试得知这个东西和上图的__proto__指向同一个 object,那么我们也就知道函数的另一个__proto__是指向它父级的Function的prototype,最终指向Object的 prototype
经过上面的调理,我们终于明白了先天靠遗传,后天靠拼搏这句话的真谛;再试着回味一下这句话
1 //2.1 直接给prototype添加属性 2 function Teacher(schoolname) { 3 this.schoolname = schoolname; 4 return this; 5 } 6 Teacher.prototype.age = 18; 7 Teacher.prototype.jiangke = function () { 8 return '老师开始讲课了'; 9 } 10 var t = new Teacher('2b1中'); 11 console.log(t.age); 12 console.log(t.schoolname); 13 console.log(t.jiangke()); 14 15 //2.2 通过prototype继承,prototype指向的是一个object,所以我们继承的话就指向父类new出来的对象就可以了 16 //这一句代码引发的长篇大论 17 function People(name) { 18 this.name = name; 19 this.say = function () { 20 return this.name + ':say what?'; 21 } 22 return this; 23 } 24 function Student(name) { 25 this.name = name; 26 } 27 Student.prototype = new People(Student.name); 28 var s = new Student('啊弥陀丸'); 29 console.log(s.say());
二、面向数据-DOP
1、初探
js面向数据编程这个概念是阿里什么论坛会上提出来的,简单的来说就是,大家懒得用js操作DOM元素了,通过直接对数据的赋值修改,然后替换到html模板中,最后直接调用innerHTML显;举个例子吧,虽然不够贴切 也不够完整,但话糙理不糙,它只是用来说明问题
这就是我们简陋的购物车,有两种水果和要购买的个数,通过+/-修改个数
1 <div id="gwcid"> 2 <p>橘子:<input type="number" value="1" /><input type="button" value="+" onclick="changeEvent('orange');" /></p> 3 <p>苹果:<input type="number" value="1" /><input type="button" value="+" onclick="changeEvent('apple');" /></p> 4 </div>
传统的方式,我们会操作DOM,然后修改它的value值;但面向数据编程的时候需要的是,得现有一个json model,然后有一个html view,把操作后的属性值relace到view中,最后innerHTML大功告成。那么这种通用的编程方式的好处自然不言而喻,而且以现在浏览器渲 染的速度,处理大数据时真是必备良品
1 var fruits = { orange: 1, apple: 1 };<br>//模板可以放入html中读取,此处为了方便 2 var tpl = '<p>橘子:<input type="number" value="<%orange%>" /><input type="button" value="+" onclick="changeEvent(\'orange\');"/></p><p>苹果:<input type="number" value="<%apple%>" /><input type="button" value="+" onclick="changeEvent(\'apple\');"/></p>'; 3 function changeEvent(name) { 4 //操作数据 5 fruits[name] += 1; 6 //替换值 7 var result = tpl.SetValue(fruits); 8 //innerHTML 9 document.getElementById('gwcid').innerHTML = result; 10 } 11 12 String.prototype.SetValue = function (json) { 13 //regex replace 14 return this.replace(/<%\w+%>?/gi, function (matchs) { 15 var str = json[matchs.replace(/<%|%>/g, "")]; 16 return str == "undefined" ? "" : str; 17 }); 18 }
2、开始及结束
经过上面的例子,相信js模板引擎啥的我们也就一并结束了吧,至少现在各种的模板引擎我也没太深入用,那些官方介绍的话也懒得贴出来了
大势所趋,现在后端许多核心的思想MVC、依赖注入、模块化等都被应用到了前段,而且连native的mvvm思想都搬了过来,说到这里,想必各位已经猜到接下来要说的东西--AngularJS,此处以文档学习为主,理论思想就懒得贴了。
2.1 Expression
1 <h3>表达式</h3> 2 <input type="number" ng-model="num1" />+<input type="number" ng-model="num2" /> 3 <p>结果为:{{num1+num2}}</p> 4 <hr /> 5 <h3>字符串</h3> 6 <div ng-init="name='lily';age=18"> 7 <p>姓名:{{name}},年龄 {{age}}</p> 8 </div> 9 <hr /> 10 <h3>对象</h3> 11 <div ng-init="student={name:'lucy',age:16}"> 12 <p>姓名:{{student.name}},年龄:{{student.age}}</p> 13 </div> 14 <hr /> 15 <h3>数组</h3> 16 <div ng-init="nums=[1,2,3,4]"> 17 <p>数组[1]:{{nums[1]}}</p> 18 <p>数组tostring:{{nums.toString()}}</p> 19 </div>
2.2 ng-
1 <!--ng-app:初始化AngularJS应用程序;ng-init:初始化应用程序数据。--> 2 <div ng-init="word='world'"> 3 hello {{word}} 4 </div> 5 6 <!--ng-model:把元素值(比如输入域的值)绑定到应用程序--> 7 请输入:<input type="text" ng-model="input" /> 8 你输入的是:{{input}} 9 10 <!--ng-show:验证不通过返回ture时显示--> 11 <p ng-show="true">可以看见</p> 12 <p ng-show="false">看不见</p> 13 <p ng-show="1=1">表达式成立可以看见</p> 14 <form action="/" method="post" ng-app="" name="form1"> 15 email:<input type="email" name="address" ng-model="email" /> 16 <span ng-show="form1.address.$error.email">请输入合法的邮箱</span> 17 <ul> 18 <li>字段内容是否合法:{{form1.address.$valid}}</li> 19 <li>表单是否有填写记录:{{form1.address.$dirty}}</li> 20 <li>字段内容是否非法:{{form1.address.$invalid}}</li> 21 <li>是否触屏点击:{{form1.address.$touched}}</li> 22 <li>是否没有填写记录:{{form1.address.$pristine}}</li> 23 </ul> 24 </form> 25 26 <!--ng-disabled:是否不可用--> 27 <button ng-disabled="true">点我!</button> 28 29 <!--ng-hide:是否可见--> 30 <p ng-hide="false">可以看见吧</p> 31 32 <!--ng-bind:绑定元素innerText的值--> 33 <div ng-init="quantity=3;cost=5"> 34 价格:<span ng-bind="quantity*cost"></span> 35 </div> 36 <div ng-init="nums2=[10,20,30]"> 37 <p ng-bind="nums2[1]"></p> 38 </div> 39 40 <!--ng-click:事件--> 41 <div ng-init="count=0;"> 42 count:{{count}} 43 <br /><button ng-click="count=count+1">+1</button> 44 </div> 45 46 <!--ng-repeat:循环指令--> 47 <div ng-init="citys=[{name:'北京',val:1},{name:'上海',val:2},{name:'广州',val:3}]"> 48 <select> 49 <option ng-repeat="x in citys" ng-bind="x.name" value="{{x.val}}"></option> 50 </select> 51 </div> 52 53 <!--ng-include:包含html内容--> 54 <div ng-include="'05service.html'"></div> 55 56 <!--自定义指令--> 57 <!--标签--> 58 <runoob-directive></runoob-directive> 59 <!--属性--> 60 <div runoob-directive></div> 61 <!--类名--> 62 <div class="runoob-directive"></div> 63 64 <script type="text/javascript"> 65 var app = angular.module("myApp", []); 66 app.directive("runoobDirective", function () { 67 return { 68 //restrict: "E", E只限元素调用,A只限属性调用,C只限类名调用,M只限注释调用 69 //replace: true,当为M为注释时,可见为true 70 template: "<h1>自定义指令!</h1>" 71 }; 72 }); 73 </script>
2.3 Scope
1 <!--ng-controller 指令定义了应用程序控制器;在controller中给$scope添加属性,view中就可以传递过去使用了--> 2 <div ng-app="myApp"> 3 <div ng-controller="ctrl"> 4 {{name}}<br /> 5 {{say();}}<br /> 6 {{$root.genname}} 7 </div> 8 <div ng-controller="ctrl1"> 9 {{$root.genname}} 10 </div> 11 </div> 12 13 <div id="div2" ng-app="myApp2" ng-controller="ctrl2"> 14 {{name}} 15 </div> 16 <script type="text/javascript"> 17 var app = angular.module('myApp', []); //'[]'用来创建依赖,没有的话 表示继续用之前创建的 18 app.controller('ctrl', function ($scope) { 19 $scope.name = 'scope'; 20 $scope.say = function () { return 'hello,sister' }; 21 }); 22 //rootScope 根作用域,作用在整个app中,可以在各个controller中使用 23 app.controller('ctrl1', function ($scope, $rootScope) { 24 $rootScope.genname = '根作用域'; 25 }) 26 var app2 = angular.module('myApp2', []); 27 app2.controller('ctrl2', function ($scope) { 28 $scope.name = '另一个作用域了'; 29 }) 30 //手动启动第二个app,记清作用域哦 31 angular.bootstrap(document.getElementById('div2'), ['myApp2']) 32 </script>
2.4 Filter
1 !--currency 格式化数字为货币格式。 2 filter 从数组项中选择一个子集。 3 lowercase 格式化字符串为小写。 4 orderBy 根据某个表达式排列数组。 5 uppercase 格式化字符串为大写。--> 6 <div ng-app="" ng-init="name='lily';citys=[{name:'北京',val:1},{name:'上海',val:2},{name:'广州',val:3}]"> 7 {{name|uppercase}} <!--表达式中添加--> 8 <ul> 9 <li ng-repeat="c in citys|filter:inp|orderBy: 'val'">{{c.name}}</li> <!--指令中过滤--> 10 </ul> 11 <input type="text" ng-model="inp"> <!--输入过滤li--> 12 </div>
2.5 Service
1 <div ng-app="myApp" ng-controller="ctrl"> 2 当前url:{{currenturl}}<br /> 3 get请求json数据:{{jsondata}} 4 自定义服务:{{myservice}} 5 </div> 6 <script type="text/javascript"> 7 //自定义服务 8 angular.module('myApp', []).service('myservice', function () { 9 this.toStartUpper = function (str) { 10 return str.substring(0, 1).toUpperCase() + str.substring(1); 11 }; 12 }); 13 14 angular.module('myApp').controller('ctrl', function ($scope, $timeout, $location, $http, myservice) { 15 $scope.currenturl = $location.absUrl(); // $location 当前页面的 URL 地址 16 $timeout(function () { //$timeout等同于window.setTimeout;$interval等同于window.setInterval 17 console.log('timeout 执行了'); 18 }, 2000);<br> //http请求 XMLHttpRequest 19 $http.get('json.txt').success(function (response) { $scope.jsondata = response; }); 20 $scope.myservice = myservice.toStartUpper('service'); 21 }); 22 </script>
2.6 api
1 <div ng-app="myapp" ng-controller="ctrl"> 2 是否是字符串:{{isstr}}<br /> 3 是否是数字:{{isnum}}<br /> 4 转为大写是:{{strtoupper}}<br /> 5 </div> 6 <script type="text/javascript"> 7 angular.module('myapp', []).controller('ctrl', function ($scope) { 8 $scope.str = 'sdfsdf'; 9 $scope.isstr = angular.isString($scope.str); 10 $scope.strtoupper = angular.uppercase($scope.str); 11 $scope.isnum = angular.isNumber($scope.str); 12 }); 13 </script>
2.7 animate
1 <!--ngAnimate 模型可以添加或移除 class 。 2 ngAnimate 模型并不能使 HTML 元素产生动画,但是 ngAnimate 会监测事件,类似隐藏显示 HTML 元素 ,如果事件发生 ngAnimate 就会使用预定义的 class 来设置 HTML 元素的动画。--> 3 <input type="checkbox" ng-model="mycheck">点我隐藏div 4 <!--添加/移除 class 的指令: 5 ng-show 6 ng-hide 7 ng-class 8 ng-view 9 ng-include 10 ng-repeat 11 ng-if 12 ng-switch 13 ng-show 和 ng-hide 指令用于添加或移除 ng-hide class 的值 14 其他指令会在进入 DOM 会添加 ng-enter 类,移除 DOM 会添加 ng-leave 属性 15 当 HTML 元素位置改变时,ng-repeat 指令同样可以添加 ng-move 类 16 --> 17 <div ng-hide="mycheck"></div> 18 <script type="text/javascript"> 19 var app = angular.module('myApp', ['ngAnimate']); 20 </script>
2.8 DI
1 var app = angular.module('myapp', []); 2 //注入value 3 app.value('defaultval', 0); 4 5 //factory 注入service 6 app.factory('sumService', function () { 7 var factory = {}; 8 9 factory.sum = function (a, b) { 10 return a + b 11 } 12 return factory; 13 }); 14 15 //自定义computeServer服务 16 app.service('computeServer', function (sumService) { 17 this.sum = function (a, b) { 18 return sumService.sum(a, b); 19 }; 20 }); 21 22 //provider 23 app.config(function ($provider) { 24 $provider.provider('sumService', function () { 25 this.$get = function () { 26 var factory = {}; 27 28 factory.sum = function (a, b) { 29 return a + b; 30 } 31 return factory; 32 }; 33 }); 34 }); 35 36 //constant 常量配置 37 app.constant('save', 'false'); 38 39 //注入的value 40 app.controller('ctrl', function ($scope, defaultval) { 41 $scope.defaultval = defaultval; 42 });
2.9 route
1 <body ng-app="myapp"> 2 <ul> 3 <li><a href="#/">首页</a></li> 4 <li><a href="#/product">产品</a></li> 5 <li><a href="#/about">关于</a></li> 6 </ul> 7 <div ng-view></div> 8 <script type="text/javascript"> 9 //添加route依赖 10 angular.module('myapp', ['ngRoute']) 11 ///$routeProvider.when(url, { 12 // template: string, 在 ng-view 中插入简单的 HTML 内容 13 // templateUrl: string, templateUrl 插入html模板文件 14 // controller: string, function 或 array, function、string或数组类型,在当前模板上执行的controller函数,生成新的scope。 15 // controllerAs: string, string类型,为controller指定别名。 16 //redirectTo: string, function, 重定向地址 17 // resolve: object<key, function> 指定当前controller所依赖的其他模块 18 // }); 19 .config(['$routeProvider', function ($routeProvider) { //$routeProvider 用来定义路由规则 20 $routeProvider.when('/', { template: '这是首页' }) //$routeProvider.when 函数的第一个参数是 URL 或者 URL 正则规则,第二个参数为路由配置对象。 21 .when('/product', { template: '这是产品' }) 22 .when('/about', { template: '这是关于我们' }) 23 .otherwise({ redirectTo: '/' }); 24 }]); 25 </script> 26 </body>
三、面向H5
html5给力之处,无非是javascript大量的api;像以前想要修改url参数不跳转做标识用,只能用#,有了pushStata 呵呵呵;更或者做webim轮询服务器,现在windows server12+websocket直接搞起(还是用signalr实在点,装逼也没人信);当然 不论是本地数据库还是websocket更或者是强大的canvas api等等等太多,其实都不如querySelector、querySelectorAll这类的api来的实在(用惯了jquery选择器的可能都这么想)
那么问题来了,既想写一套代码,又想用h5新api的写法,跟着潮流 不然就out了;那么就需要兼容IE8及下,为他们实现h5这些个常用的api就好了撒
思想已经出来了,但雏形还未跟上,虽然很简单,但是我还是厚着脸皮写出来了
1 <input type="text" id="inputid" name="name" value="none" /> 2 <script type="text/javascript"> 3 if (!window.localStorage) { 4 document.write('<script src="xxx.js"><\/script>'); 5 //document.write('<script src="jquery-1.9.1.js"><\/script>'); 6 //(function (d) { 7 // d.query = function (selector) { 8 // return $(selector)[0]; 9 // } 10 // Element.prototype.addEvent = function (types, fn) { 11 // return $(this).bind(types, fn); 12 // } 13 //})(document); 14 } 15 window.onload = function () { 16 var obj = document.query('#inputid'); 17 console.log(obj.value); 18 obj.addEvent('change', function () { 19 console.log(this.value); 20 }) 21 }; 22 </script>