原型链与继承

一.原型链机制

1. 原型链的本质

只要是对象,一定有原型对象(除原型链终点外),就是说只要这个东西是个对象,那么一定有__proto__属性。

原型链的终点Object.prototype , 该对象没有原型对象

function People() {

}

var obj = new People()

console.log(obj.__proto__) // People {}

console.log(obj.__proto__.__proto__) // {}

console.log(obj.__proto__.__proto__.__proto__) // null

Object是一个函数,是系统内置的构造函数,用于创造对象的。Object.prototype是所有对象的原型链终点。

所以,当我们在一个对象上打点调用某个方法的时候,系统会沿着原型链去寻找它的定义,一直找到Object.prototype。

Object.prototype是所有对象原型链的终点

Object.prototype是所有对象的原型链的终点,所以我们直接给Object.prototype增加一个方法,那么世界上所有的对象都能调用这个方法:

2. 引用类型的构造函数

所有的引用类型值,都有内置构造函数。比如

new Object()

new Array()

new Function()

new RegExp()

new Date()

// 现在是一个数组字面量
var arr = [66,4343,23];
// arr.haha = 23;
// console.log(arr.haha); //23

console.log(arr.__proto__);   // 不用管,直接看constructor
console.log(arr.__proto__.constructor);

// 寻找原型链的终点,发现是Object.prototype
console.log(arr.__proto__.__proto__.constructor)
3. 基本类型的包装类

基本类型值,也有包装类型。所谓包装类型,就是它的构造函数。

new Number()

new String()

new Boolean()

二. 对象与属性

判断属性是否存在

1. 对象直接打点验证某个属性是否存在

对象打点调用属性,我们之前的课程已经讲过,遍历原型链。所以就可以看出来属性是否在自己身上或原型链上。如果在,就返回值;如果不在就返回undefined.

4. instanceof 运算符
A instaceof B

验证A对象的原型链上有没有对象是通过构造函数B, new出来的对象

三. 继承

1. 原型链继承

将父类的实例作为子类的原型

// 父类型
function Supper() {
    this.superProp = 'super property'
}

Supper.prototype.showSupperProp = function () {
    console.log(this.superProp)
};


// 子类型
function Sub() {
    this.subProp = 'sub property'
}

// 子类型的原型为父类型的一个实例对象
Sub.prototype = new Supper();

// 子类型调用父类型的方法
new Sub().showSupperProp();
2. 构造函数继承

使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

function People(name){
    this.name = name;
}
People.prototype.sayHello = function(){
    alert("你好我是" + this.name);
}

function Student(name,xuehao){
    //  核心语句call 修改this指向
    // 继承父类的name属性
    People.call(this, name);

    this.xuehao = xuehao;
}

Student.prototype.study = function(){
    alert("好好学习,天天向上");
}

var xiaohong = new Student("小红",1001);

方法都在构造函数中定义, 只能继承父类的实例属性和方法,不能继承原型属性/方法,无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

3. 组合继承

就是将原型链继承和构造函数继承组合在一起;继承两个优点

通过调用父类构造,继承父类的属性并保留传参的优点,

然后再通过将父类实例作为子类原型,实现函数复用

function People(name){
    this.name = name;
}
People.prototype.sayHello = function(){
    alert("你好我是" + this.name);
}

function Student(name,xuehao){
    People.call(this,name);
    this.xuehao = xuehao;
}

//核心语句,继承的实现全靠这条语句了:
Student.prototype = new People('大明');

Student.prototype.study = function(){
    alert("好好学习,天天向上");
}

var xiaohong = new Student("小红",1001);

xiaohong.sayHello();

调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值