标签:
function factorial(num){ if(num<=1){ return 1; }else{ return num = num * factorial(num-1); } } 改进 function factorial(num){ if(num<=1){ return 1; }else{ return num = num * arguments.callee(num-1); } } var factorial = function f(num){ if(num<=1){ return 1; }else{ return num = num * f(num-1); } } 有权访问私有变量和私有函数的公有方法称为特权方法 function person(name){ this.getName = function () { return name; } this.setName = function (value) { name = value; } 在构造函数中定义特权方法必须使用构造函数模式来实现这个目的 缺点 针对每个实例都会创建同样一组新方法 静态私有变量实现特权方法 (function(){ var name = ""; Person = function (value) { name = value; } Person.prototype.getName = function () { return name; } Person.prototype.setName = function (value) { name = value; } })() 使用原型增进了代码复用 但是每个实例都没有自己的私有变量 模块模式 为单例创建私有变量和特权方法 var singleton = function () { //私有变量和函数 var components = new Array(); //初始化 components.push(new BaseComponents); //公共 return { getComponentCount : function(){ return components.length; } registerComponent : function(component){ if(typeof component =="object"){ components.push(component); } } } } (); 增强模块模式 适用于单例必须是某种类型的实例 var application = function () { //私有变量和函数 var components = new Array(); //初始化 components.push(new BaseComponent()); //创建application的一个局部副本 var app = new BaseComponent(); //公共 app.getComponentCount = function(){ return components.length; } app.registerComponent = function(component){ if(typeof component =="object"){ components.push(component); } } return app; }(); 创建对象 工厂模式 function createPerson(name, age, job){ var o = new object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } 构造函数模式 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } //等价于 this.sayName = new Function ("alert(this.name)"); } Person大写开头 构造函数意味着将来可以把它的实例标识为一种特定的类型 缺点:每个方法都要在每个实例上重新创建一遍 原型模式 function Person(){ Person.prototype.name = name; Person.prototype.age = age; Person.prototype.job = job; Person.prototype.sayName = function(){ alert(this.name); } } [[prototype]] __proto__ isPrototypeOf() es5 Object.getPrototypeOf(0) 这个指针链接存在于实例和构造函数的原型对象之间 function hasPrototypeProperty(object, name){ return !object.hasOwnProperty(name) && (name in object); } for in 返回所有能偶通过对象访问的 可枚举的属性 ie早期bug 屏蔽不可枚举属性的实例属性不会出现在for in ex:toString() 取得对象上所有可枚举的实例属性 Object.keys() 取得所有实例属性 无论是否可枚举 Object.getOwnPropertyNames() ex:constructor function Person(){} Person.prototype = { //constructor :Person, 但是其[[Enumerable]]为true 默认是false的 name : "zz", age : 25, job : "Software Engineer" sayName : function(){ alert(this.name); } } 注意: var friend = new Person(); friend.constructor == Object 因为重写了默认的prototype对象 可以修改原生对象的原型 但是不建议 可能导致命名冲突 也可能意外的重写了原生方法 问题·:原型模式省略了为构造函数传递初始化参数,结果所有实例在默认情况下取得相同的值 对于包含引用类型值得属性就会出问题 相互影响 如数组 组合模式 构造函数和原型 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["aa","bb"]; //放在原型中就出现上面问题 } Person.prototype = { constructor :Person, this.sayName = function(){ alert(this.name); } 动态原型 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); } } } 这里对原型的修改立即会在所有实例中得到反应 动态原型 不能使用对象字面量重写原型 重写会切断指针联系 寄生构造函数模式 function Person(name, age, job){ var o = new object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } 特殊情况下用来为对象创建构造函数,如创建一个具有额外方法的特殊数组 返回的对象和构造函数或者构造函数的原型没有关系 不能依赖instanceof 一般不建议使用 稳妥构造函数模式 function Person(name, age, job){ var o = new object(); o.sayName = function(){ alert(name); } return o; } 安全环境适用 不引用this 不用new操作符调用 除了sayName 没有办法再访问到name 继承 原型链 终点Object.prototype instanceof isPrototype() 子类定义方法或重写超类方法一定要放在替换原型语句后 即:SubType.prototype = new SuperType();之后 不要使用字面量创建原型方法 一样存在引用值共享 无法向超类传递参数的问题 借用构造函数 function SuperType(name){ this.name = name; } function subType(){ //继承了SuperType 同时传递了参数 SuperType.call(this, "zz"); this.age = 25; } 仅构造函数无法避免方法都在构造函数中定义了 无法函数复用 组合继承 function SuperType(name){ this.name = name; this.colors = ["red","blue"]; } SuperType.prototype.sayName = function(){ alert(this.name); } function SubType(){ //继承了SuperType SuperType.call(this, name); //第二次 this.age = 25; } //继承方法 SubType.prototype = new SuperType(); //第一次 //创建子方法 SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); } 无论什么情况下都会调用两次超类构造函数 不得不在调用子类型构造函数时重写这些属性 原型式继承 function object(o){ function F(){}; F.prototype = o; return new F(); } 本质上object()对传入的o完成了一次浅复制 前提必须有一个对象可以作为另一个对象的基础 ES5 Object.create()方法规范原型式继承 两个参数 一个用做新对象原型的对象 一个为新对象定义额外属性的对象 一样有引用类型值问题 寄生式继承 function createAnother(original){ var clone = object(original); //以某种方式来增强这个对象 clone.sayHi = function(){ alert("hi"); } return clone; } 主要考虑对象而不是自定义类型和构造函数下适用 不能复用 寄生组合式继承 解决组合继承调用两次超类构造函数(第二次调用产生的属性屏蔽了第一次调用原型中的同名属性) 不必为了指定子类型的原型而调用超类型的构造函数 所需的无非是超类型原型的副本 function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); //弥补重写原型而失去的默认constructor属性 prototype.constructor = subType; subType.prototype = prototype; } unction SuperType(name){ this.name = name; this.colors = ["red","blue"]; } SuperType.prototype.sayName = function(){ alert(this.name); } function SubType(){ SuperType.call(this, name); this.age = age; } inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function(){ alert(this.age); } 只调用了一次SuperType 避免了在SubType.prototype上创建不必要、多余的属性 同时原型链保持不变 正常使用instanceof isPrototype() YUI的YAHOO.lang.extend() 采用了
标签:
原文地址:http://www.cnblogs.com/bgstyle/p/4374329.html