让学习“上瘾”,成为更好的自己!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>原型链</title>
<script>
/*
许多OO语言支持2种继承方式:接口继承和实现继承
接口继承:继承方法签名
实现继承:继承实际方法
因为函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承(主要依靠原型链)
原型链: (基本思想)利用原型让一个引用类型继承另一个引用类型的属性和方法
*/
// function SuperType(){
// this.property = true;
// }
// SuperType.prototype.getSuperValue = function(){
// return this.property;
// }
// function SubType(){
// this.subProperty = false;
// }
// 这里的“继承” --> 重写原型对象,取而代之的是一个新类型的实例
// 实际上,不是SubType的原型的constructor属性被重写了,而是SubType的原型指向了另一个对象 —— SuperType的原型,而这个原型对象的constructor属性指向的是SuperType
// SubType.prototype = new SuperType();
// console.log(SubType.prototype);
// SubType.prototype.getSubValue = function(){
// return this.subProperty;
// }
// var instance = new SubType();
// console.log(instance.getSuperValue()); // true
// console.dir(instance);
// console.dir(instance.__proto__);
// console.dir(SubType.prototype);
// 【总结】通过实现原型链,本质上扩展了本章界山的“原型搜索机制”
// 1, 别忘记默认的原型
// 所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.prototype
// 例如,当调用instance.toString()时,实际上调用的是保存在Object.prototype中的方法
// 2, 确定原型和实例的关系
// (1)方式1:使用instanceof操作符 --> 用这个操作符测试实例与原型链中出现过的构造函数,就会返回true
// console.log(instance instanceof Object); // true
// console.log(instance instanceof SuperType); // true
// console.log(instance instanceof SubType); // true
// (2) 方式2:使用isPrototypeOf()方法 --> 只要原型链中出现过的原型,都可以说是该原型链所派生的实例的原型,结果会返回true
// console.log(Object.prototype.isPrototypeOf(instance)); // true
// console.log(SubType.prototype.isPrototypeOf(instance)); // true
// console.log(SuperType.prototype.isPrototypeOf(instance)); // true
// 3, 谨慎地定义方法
// (1) 不管是重写超类型中的方法,或者添加方法,给原型添加方法的代码一定要放在替换原型的语句之后
// function SuperType(){
// this.property = true;
// }
// SuperType.prototype.getSuperValue = function(){
// return this.property;
// }
// function SubType(){
// this.subProperty = false;
// }
// // 继承了SuperType
// SubType.prototype = new SuperType();
// // 添加新方法
// SubType.prototype.getSubValue = function(){
// return this.subProperty;
// }
// // 重写超类型中的方法
// SubType.prototype.getSuperValue(){
// return "i was changed!!";
// }
// var instance = new SubType();
// console.log(instance.getSuperValue());
// (2) 在通过原型链实现继承时,不能使用“对象字面量”创建原型方法 --> 因为这样会重写原型链
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
}
function SubType() {
this.subProperty = false;
}
SubType.prototype = new SuperType();
// 使用字面量添加新方法,会导致上一行代码无效!!
SubType.prototype = { // Object实例
getSubValue: function () {
return this.subProperty;
},
someOtherMethod: function () {
return false;
}
};
var instance = new SubType();
// console.log(instance.getSuperValue()); // error
console.dir(instance);
// 4, 原型链的问题
// (1) 包含引用类型值的原型 --> 包含引用类型值的原型属性会被所有实例共享(基本包含类型则不会!!)
// (2) 在创建子类型的实例时,不能向超类型的构造函数中传递参数
// 或者说,没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数
// 【注意】很少单独使用!!!
</script>
</head>
<body>
</body>
</html>