prototype

文章目录

创造对象的形式

工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function createObj(name, age, fn) {
var obj = {
// ES6 中,如果属性名和属性值的参数名一样,可以省略 自动变成 name: name, age: age
name,
age,
eatFn: fn
}
return obj
}
function eatFn() {}
var dog = createObj('dog', 8, eatFn)
var person = createObj('person', 20, eatFn)
// 也可以用 new 来创造,效果一样
// 工厂模式的缺点是,实例的原型对象都是 Object,而不会区分 Dog 或者 Person,没有实现函数复用,每个实例上都开辟了自己的区域存储函数,函数都存于自身对象上,而不是引用父类的函数
// 虽然 dog.eatFn === person.eatFn // true ,他们引用的确实是一个同函数

构造函数模式

1
2
3
4
5
6
7
8
9
10
11
12
function createObj(name, age, fn) {
this.name = name
this.age = age
}
function eatFn() {}
createObj.prototype.eatFn = eatFn //
var dog = new createObj('dog', 11) // 必须 new,否则将创建 window.age ,并将它赋值为 1
// 解决了函数复用的问题,只要修改构造函数名字就可以区分每个实例的原型,即上面的区分 Person 和 Dog,function Person() {}和function Dog() {},这样建两个就行。
createObj.prototype = {eatFn}
var cat = new createObj('cat', 11)
console.log(dog.__proto__) // {eatFn: f, constructor: f}
console.log(cat.__proto__) // {eatFn: f} 给 prototype 用字面量赋值会丢失 constructor

继承(推荐使用寄生组合继承)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 寄生组合继承
function Cat(name){
Animal.call(this); // 调用父类构造函数
this.name = name || 'Tom';
}
// 从组合继承上发展,把 Cat.prototype = new Animal(); // 调用父类函数, 被屏蔽,因为在子类实例中就能找到属性,不会去原型上找,一般情况下无所谓,但如果删除了实例上的属性,实际上在子类原型上还能访问到,就会出现意想不到的结果
// 所以算到这里调用了两次父类函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了),多消耗了一点内存而且有上面说的弊端,所以有了寄生组合继承
// 变成了下面的匿名函数
(function(){
// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
})();
Cat.prototype.constructor = Cat; // 需要修复下构造函数,寄生组合继承和组合继承都需要修复 constructor 的指向

// 可以改写成 Cat.prototype = Object.create(Animal.prototype) 代替 Super 构造函数
// 它复制了一份 Animal.prototype,并将他的this 指向 Object.create 创造的空对象,之后把这个对象赋值给 Cat.prototype


// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

// 附录 Animal 构造函数
function Animal (name) {
// 属性
this.name = name || 'Animal';
/* 原来下面的 Animal 的原型上的方法写在这里的,但写在这里,所有实例就都会有自己的方法,没有从原型链上获取。
// 实例方法
Animal.prototype.sleep = function(){
console.log(this.name + '正在睡觉!');
}
*/
//实例引用属性
this.features = [];
}
// 实例方法
Animal.prototype.sleep = function(){
console.log(this.name + '正在睡觉!');
}
Cat.prototype = new Animal();
分享到:

评论完整模式加载中...如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理