凯发ag旗舰厅登录网址下载
收集整理的这篇文章主要介绍了
javascript | 继承
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
—————————————————————————————————————————————————————————
继承 - ecmascript只支持实现继承(依靠原型链),不支持接口继承(函数没有签名)
原型链
- 利用原型让一个引用类型继承另一个引用类型的属性和方法,
- 构造函数、原型、实例的关系:每个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针。实例包含一个指向原型对象的内部指针,在创建实例之后即指向原型对象
- 而当a原型对象的指针指向b个原型对象时(此时a原型对象与b实例同级),就形成了一条原型链。
- 图解:
原型搜索机制:当读取模式访问一个实例属性时,首先会在实例中搜索该属性,如果没有找到该属性则沿着原型链向上查找
在例子中,调用instance.getsupervalue(),先搜索实例instance,再搜索subtype.prototype,再搜索supertype.protorype,最后一步才找到该方法。
默认的原型:所有的引用类型默认都继承了object,所以默认原型的指针都会指向object.prototype,完整的原型链如下:
instance → subtype.prototype → supertype.prototype → object.prototype
- p.s.
必须替换掉实例的原型后才能给实例添加方法
不能使用对象字面量创建原型方法,这样做会重写原型链,如
- 缺点:
包含引用类型值(function object array)的原型属性会被所有实例共享,在通过原型来实现继承时,原型实际上会变成另一个类型的实例,所以原先的实例属性就变成了现在的原型属性了。
在创建子类型的实例时,不能向超类型的构造函数中传递参数。
// "use strict";// demo - 1
// supertype 拥有一个属性和一个方法
// subtype 拥有一个属性和一个方法,又从supertype那里继承了一个属性一个方法
function supertype(){this.property = "111"
;
}
supertype.prototype.getsupervalue =
function(){return this.property;
}
function subtype(){this.subproperty = "222"
;
}
// p.s.new操作之前,subtype.prototype指向的是function,不允许为function()定义.getsubvalue方法,所以要将添加方法放在修改原型指向之后
// 操作之后subtype.prototype指向supertype
subtype.prototype =
new supertype();
subtype.prototype.getsubvalue =
function(){
// 必须在subtype替换原型之后才能定义return this.subproperty;
}
var instance =
new subtype();
console.log(instance.property); // 111
console.log(instance.getsupervalue());
// 111
console.log(instance.subproperty);
// 222
console.log(instance.getsubvalue());
// 222
console.log(instance.constructor);
// f supertype(){} 原本subtype中的constructor属性被重写
// 重写supertype.getsupervalue()
// 如果要重写这个方法,会屏蔽原来的方法
// 换句话说,当通过subtype的实例调用getsupervalue时调用的就是这个重新定义的方法,但通过supertype的实例调用时还会继续调用原来的方法
var beforerewrite =
new supertype();
supertype.prototype.getsupervalue =
function(){console.log("rewrite"
);
}
console.log(instance.getsupervalue()); // rewrite,this.property = undefined
console.log(supertype.prototype.getsupervalue());
// rewrite,this.property = undefined
console.log(beforerewrite.getsupervalue());// demo - 2
// 确认原型和实例的关系
console.log(instance
instanceof object);
// true
console.log(instance
instanceof supertype);
// true
console.log(instance
instanceof subtype);
// true
// 另一种方法
console.log(object.prototype.isprototypeof(instance));
// true
console.log(supertype.prototype.isprototypeof(instance));
// true
console.log(subtype.prototype.isprototypeof(instance));
// true// demo - 3
function supertype2(){this.property = "1111"
;
}
supertype2.prototype.getsupervalue =
function(){return this.property;
}
function subtype2(){this.subproperty = "2222"
;
}
subtype2.prototype =
new supertype2();
subtype2.prototype =
{getsubvalue:function(){return this.subproperty;},someothermethod:function(){return false;}
}
var instance2 =
new subtype2();
console.log(instance2 instanceof object);
// true
console.log(instance2
instanceof supertype2);
// false,原型链被切断
console.log(instance2
instanceof subtype2);
// true
// console.log(instance2.getsupervalue()); // error// demo - 4
function supertype3(){this.colors = ["red","blue","green"
];
}
function subtype3(){}
subtype3.prototype =
new supertype3();
var instance3 =
new subtype3();
instance3.colors.push("black"
);
console.log(instance3.colors); // ["red", "blue", "green", "black"]
var instance4 =
new subtype3();
console.log(instance4.colors); // ["red", "blue", "green", "black"]
借用构造函数(伪造对象 / 经典继承)
// "use strict";function supertype(name) {this.name =
name;this.colors = ["111", "222", "333"
];
}function subtype() {supertype.call(this, "name1"
);this.age = 20
;
}var instance =
new subtype();
instance.colors.push("444"
);
console.log(instance.colors); // ["111", "222", "333", "444"]
console.log(instance.name);
// name1
console.log(instance.age);
// 20
var instance2 =
new subtype();
console.log(instance2.colors); // ["111", "222", "333"]
组合继承(伪经典继承)
- 将原型链和借用构造函数组合,使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承
- 对应创建对象 <组合使用构造函数模式和原型模式>
- 优点:最常用
- 缺点:需要调用两次超类型构造函数,一次在创建子函数原型时,另一次在子函数构造函数内部。调用子类型构造函数时需要重写属性
// "use strict";
function supertype(name) {this.name =
name;this.colors = ["111", "222", "333"
];
}
supertype.prototype.sayname =
function() {console.log(this.name);
}function subtype(name, age) {supertype.call(this, name);
// 继承属性this.age =
age;
}
subtype.prototype =
new supertype();
// 继承方法
subtype.prototype.constructor =
subtype;
subtype.prototype.sayage =
function() {console.log(this.age);
}
var instance1 =
new subtype("hugh", 20
);
instance1.colors.push("444"
);
console.log(instance1.colors); // ["111", "222", "333", "444"]
instance1.sayname();
// hugh
instance1.sayage();
// 20
var instance2 =
new subtype("dong", 21
);
console.log(instance2.colors); // ["111", "222", "333"]
instance2.sayname();
// dong
instance2.sayage();
// 21
原型式继承
// "use strict";
function object(o){function f(){}
// 创建临时性构造函数f.prototype = o;
// 将传入的对象作为构造函数的原型return new f();
// 返回临时类型的一个新实例
}var person =
{name:"hugh"
,friends:["111",'222','333'
]
};var anotherperson =
object(person);
anotherperson.name = "dong"
;
anotherperson.friends.push("444"
);var yetanotherperson =
object(person);
yetanotherperson.name = "hehe"
;
yetanotherperson.friends.push("555"
);console.log(person.friends); // ["111", "222", "333", "444", "555"]
console.log(person.name);
// hugh
console.log(anotherperson.friends);
// ["111", "222", "333", "444", "555"]
console.log(anotherperson.name);
// dong
console.log(yetanotherperson.friends);
// ["111", "222", "333", "444", "555"]
console.log(yetanotherperson.name);
// hehe// 使用object.create()规范化原型式继承
// 以这种方式指定的任何属性都会覆盖原型对象上的同名属性
var otherperson1 =
object.create(person);
otherperson1.friends.push("666"
);
console.log(yetanotherperson.friends); // ["111", "222", "333", "444", "555", "666"]
var otherperson2 =
object.create(person,{name:{value:"test"
}
});
console.log(otherperson2.name);
寄生式继承
- 对应创建对象 <寄生构造函数 / 工厂模式>
- 创建一个仅用于封装继承过程的函数,在内部增强对象,最后返回对象
- 示范集成模式时使用的object()函数不是必须的,任何能够返回新对象的函数都适用于此模式
- 使用场景:在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式
- 缺点:无法做到函数复用,类似于构造函数模式
// "use strict";
function object(o) {function f() {}
// 创建临时性构造函数f.prototype = o;
// 将传入的对象作为构造函数的原型return new f();
// 返回临时类型的一个新实例
}function createanother(original) {
// 接收的函数作为新对象基础的对象var clone =
object(original);clone.sayhi =
function() {
// 添加新方法console.log('hi'
);};return clone;
}
var person =
{name: "hugh"
,friends: ['111', '222', '333'
]
};
var person1 =
createanother(person);
person1.sayhi();
console.log(person1.name);
console.log(person1.friends);
寄生组合式继承
- 优点:
最理想的继承范式
解决组合继承重写属性的问题,只调用了一次supertype构造函数
避免了在subtype.prototype上创建不必要的属性
原型链保持不变
能够正常使用instanceof和isprototypeof()
"use strict"
;
function object(o) {function f() {}f.prototype =
o;return new f();
}// 1.创建超类型原型的一个副本
// 2.为创建的副本添加constructor属性,弥补因重写原型而失去的属性
// 3.将新创建的对象(即副本)赋值给子类型的原型
function inheritprototype(subtype,supertype){var prototype = object(supertype.prototype);
// 创建对象prototype.constructor = subtype;
// 增强对象subtype.prototype = prototype;
// 指定对象
}
function supertype(name){this.name =
name;this.colors= [1,2,3,4
];
}
supertype.prototype.sayname =
function(){console.log(this.name);
}
function subtype(name,age){supertype.call(this,name);this.age =
age;
}
inheritprototype(subtype,supertype);
subtype.prototype.sayage =
function(){console.log(this.age);
}
转载于:https://www.cnblogs.com/hughdong/p/7264122.html
总结
以上是凯发ag旗舰厅登录网址下载为你收集整理的javascript | 继承的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。