【JS】原型继承
1. 对象原型:
对象原型为JS中对象的一个特殊的隐藏属性[[Prototype]],值为一个对象的引用或者null,引用所指向的对象为原型
2. 原型继承:
当读取一个对象的属性时,若没有,会自动从原型链中寻找。
一、原型链继承
// Supper函数
function Supper(){
this.supProp = 'supper prop'
}
// Supper函数原型上添加一个方法
Supper.prototype.showSupper = function(){
console.log(this.supProp);
}
// Sub函数
function Sub(){
this.subProp = 'sub Prop'
}
Sub.prototype = new Supper() // 将Sub函数的原型设置为一个Supper实例对象
Sub.prototype.constructor = Sub // 在Sub原型中添加一个constructor属性,执行Sub函数自身
// Sub原型上添加方法
Sub.prototype.showSub = function(){
console.log(this.subProp);
}
// 创建一个Sub实例
const s = new Sub()
console.log(s)
s.showSub()
s.showSupper()
pp
二、结合构造函数
function Person(name,age){
this.name = name;
this.age = age
}
Person.prototype.setName = function(name){
this.name = name;
};
function Student(name,age,price){
Person.call(this,name,age);//相当于this.Person(name,age)
this.price = price;
}
Student.prototype = new Person();//为了看到父类型方法
Student.prototype.constructor = Student;//修正constructor属性
Student.prototype.setPrice = function(price){
this.price = price;
};
var s = new Student('Tom',24,1500);
s.setName('Bob');
s.setPrice(100);
console.log(s.name,s.age,s.price);
pp
3. 设置原型[[Prototype]]的方法:
1. 使用__proto__,获取或设置对象原型。
2. 使用Object.setPrototypeOf 或 Object.getPrototypeOf
* __proto__ 是 [[Prototype]] 的因历史原因而留下来的 getter/setter,现代编程语言建议我们应该使用函数 Object.getPrototypeOf/Object.setPrototypeOf 来取代 __proto__ 去 get/set 原型
4. **原型只用于读取属性**
写入/删除操作不用使用原型,直接加在对象身上即可。
但访问器属性,赋值操作时由setter函数执行。若将对象身上写入一个属性,该属性为原型中访问器属性,则会调用原型中的setter和getter。
5. this问题:
**调用 obj.method(),无论在哪里找到方法:在一个对象还是在原型中。在一个方法调用中,this 始终是点符号 . 前面的对象。**
let animal = { eat() { this .full = true ; } }; let rabbit = { __proto__: animal }; rabbit.eat();
属性查找和执行是两回事儿。
首先在原型中找到 rabbit.eat
方法,然后在 this=rabbit
的情况下执行。
6. for..in循环会迭代继承的属性
但几乎所有其他键/值获取方法都忽略继承的属性
Object.keys()只会返回自己的key
内建方法obj.hasOwnProperty(key),若obj自身有该属性则返回true,没有返回false
7. 性能
在现代引擎中,从性能的角度来看,我们是从对象还是从原型链获取属性都是没区别的。它们(引擎)会记住在哪里找到的该属性,并在下一次请求中重用它。一旦有内容更改,它们就会自动更新内部缓存,因此,该优化是安全的。