prototype
function
才会有的属性
__proto__
所有对象都有的属性,但不是标准属性,是部分浏览器提供的
一般可以认为:
__proto__
===constructor.prototype
不过也有例外,如果修改了prototype的指向,此等式就不成立了。
function Foo(){
this.name='Tom';
}
var obj = {};
console.log(obj.__proto__);//{}
console.log(obj.__proto__ === obj.constructor.prototype) //true
var fo = new Foo();
console.log(fo.__proto__); //Foo{}
console.log(fo.__proto__ === fo.constructor.prototype); //true
var foo = Object.create(fo);
console.log(foo.__proto__); //Foo{}
console.log(foo.__proto__ === foo.constructor.prototype); //false
因为:Object.create() 会把prototype重新赋值
Object.create = function(o){
var F = Function(){};
F.prototype = o;
return new F();
}
此时 foo.constructor.prototype === fo.__proto__
原型模型:
Function.prototype = {
constructor : Function
,__proto__ : parent prototype
[,other prototypes : ....]
}
原型所带来的问题
虽然原型对面向对象的实现带了来便利,但是与此同时也带来了缺点:
- 没有了构造函数传递初始化的过程,这个在某种程度上带来了一些不便
- 最大的问题是引用的特性,带来了数据共享的问题
function Person(){}
Person.prototype = {
constructor : Person,
name : 'tom',
age : 10,
hobbies : ['book','gril']
}
let person1 = new Person();
let person2 = new Person();
person1.hobbies.push('boy');
console.log(person1.hobbies); // 'book','gril','boy'
console.log(person2.hobbies); // 'book','gril','boy'
### 解决办法:使用构造函数模式
构造函数模式和原型模式混用
function Person(name,age){ this.name = name; this.age = age; this.hobbies = ['book','gril'] } Person.prototype = { constructor : Person, sayName : () => { console.log(this.name); } } let person1 = new Person('tom',10); let person2 = new Person('jim',11); person1.hobbies.push('boy'); console.log(person1.hobbies); //['book','gril','boy'] console.log(person2.hobbies); //['book','gril'] console.log(person1.sayName === person2.sayName); // true
动态构造模式
function Person(name, age){ this.name = name; this.age = age; if(typeof this.sayName != 'function'){ Person.prototype.sayName = () =>{ console.log(this.name); }; } } let person = new Person('tom', 1); person.sayName();//tom
只有在sayName不存在的情况下构造实例时才会初始化到原型中,且初始化完成后会立即体现在所有实例中。
寄生构造模式
function Person(name, age, hobbies){ let t = new Object(); t.name = name; t.age = age; t.hobbies = hobbies; t.sayName = function() { console.log(this.name); }; return t; } let person1 = new Person('tom', 10,['a','b']); let person2 = new Person('jim',11,['a','b','c']); person1.sayName(); //'tom' person2.sayName(); //'jim; console.log(person1.hobbies); //[ 'a', 'b' ] console.log(person2.hobbies); //[ 'a', 'b', 'c' ]
细心的同学会发现,这种模式和工场模式一模一样。
稳妥构造函数模式
function Person(name, age) { var t = {}; t.sayName = () => { console.log(name); }; return t; } let person = new Person('tom', 11); person.sayName(); //'tom'
此种模式下只能通过sayName才能访问到name属性。
稳妥模式的思想就是不引入this,这在一些不能用this的场景中很有必要。