06月 10 prototype 发表于 2020-06-10 • 字数统计 787 文章目录创造对象的形式工厂模式构造函数模式继承(推荐使用寄生组合继承) 创造对象的形式工厂模式123456789101112131415function 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 ,他们引用的确实是一个同函数 构造函数模式123456789101112function 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 继承(推荐使用寄生组合继承)12345678910111213141516171819202122232425262728293031323334353637383940414243444546// 寄生组合继承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 Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // trueconsole.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(); 分享到: 赞赏 微信扫一扫,向我赞赏 支付宝扫一扫,向我赞赏