看《JavaScript高级程序设计》做的一些笔记
工厂模式:
function createPerson(arguments){ var o = new Object(); o.name = name; o.age = age; o.sayName = function(){}; return o; } var person1 = createPerson(arguments);
解决创建多个相似对象的问题
缺点:
没有解决对象识别问题
构造函数模式:
function Person(arguments){ this.name = name; this.age = age; this.sayName = function(){}; } var person1 = new Person(arguments); var person2 = new Person(arguments);
构造函数名大写字母开头
person1有constructor(构造函数)属性,指向Person
person1.constructor == Person //true
person1 instanceof Object //true
person1 instanceof Person //true
构造函数当做普通函数使用,属性和方法都添加给window
缺点:
每个方法在每个实例上都要重新创建一遍
person1.sayName == person2.sayName //false
原型模式:
每个函数都有一个prototype属性,指向一个对象,这个对象可以包含特定类型所有实例共享的属性和方法function Person(){ } Person.prototype.name = 'myName'; Person.prototype.age = 66; Person.prototype.sayName = function(){}; var person1 = new Person(); var person2 = new Person(); person1.name == person2.name //myName
person1.name = 'newName';
person1.name //newName(来自实例)
person2.name //myName (来自原型)
访问属性时,若没有在实例中搜索到该属性,就会在原型中搜索并返回该属性
使用delete可以删除实例中的属性,此时再访问该属性则会返回原型中的属性
delete person1.name;
person1.name //myName (来自原型)
原型与in操作符:
通过对象能够访问属性时返回true(for-in返回能够通过对象访问的、可枚举的属性),无论是在实例中还是原型中原型模式的一些方法:
isPrototypeOf()Person.prototype.isPrototypeOf(person1) //true
Object.getPrototypeOf(person1) == Person.prototype //true
Object.getPrototypeOf(person1.name) //myName
hasOwnProperty() 检测一个属性是否存在于实例中
person1.name = 'newName';person1.hasOwnProperty('name'); //true
person2.hasOwnProperty('name'); //false
hasPrototypeProperty() 检测一个属性是否来自原型
hasPrototypeProperty(person1,'name'); //falsehasPrototypeProperty(person2,'name'); //true
Object.keys() 取得对象上所有可枚举的实例属性
Object.getOwnPropertyNames() 获取所有实例属性,无论是否可枚举
原型的对象字面量写法
function Person(){ } Person.prototype = { name:'myName', age:66, sayName:function(){} };
这种写法的constructor属性不再指向Person,而是指向Object构造函数
var person3 = new Person();
person3 instanceof Person //true
person3 instanceof Object //true
person3.constructor == Person //false
person3.constructor == Object //true
缺点:
由于其共享的特性,对于包含引用类型值的属性,实例无法有属于自己的属性
例如属性中包含数组,若通过实例对象对数组进行修改,由于数组存在于prototype中,则会影响到所有的实例。
组合使用构造函数模式和原型模式(广泛使用):
构造函数模式定义实例属性,原型模式用于定义方法和共享的属性function Person(arguments){ this.name = name; this.age = age; this.friends = ['a','b']; } Person.prototype = { constructor:Person, sayName:function(){} };
动态原型模式:
function Person(arguments){ //属性 this.name = name; this.age = age; //方法 if(typeof this.sayName != 'function'){ Person.prototype.sayName = function(){}; Person.prototype.otherFunction = function(){}; } }
寄生构造函数模式:
function Person(arguments){ var o = new Object(); o.name = name; o.age = age; o.sayName = function(){}; return o; }
var person1 = new Person(arguments);
除了使用new和构造函数,这个模式跟工厂模式是一样的
例如要创建一个具有额外功能的Array,由于不能直接修改Array,可以这样:
function SpecialArray(){ var sa = new Array(); sa.push.apply(sa,arguments); //使用apply是因为push如果接收数组作为参数,会将整个数组当做一个元素push sa.newFunction = function(){}; } var arr = new SpecialArray(arguments); arr.newFunction();
稳妥构造函数模式(安全性考虑):
function Person(name,age){ var o = new Object(); o.sayName = function(){ return name; } return o; } var person1 = Person(name,age); person1.sayName(); //除了使用sayName()方法之外没其他办法访问到name的值