【原型链】JS中的原型链到底是什么

1.构造函数

JS中的构造函数和普通函数没有本质区别,要用调用方式的不同来区分。

在调用构造函数时要用new Func()的方法来调用,此时函数会默认返回this

为了与普通函数区分,构造函数的函数名一般以大写字母开头。

function Person(name,age){
    this.name=name;
    this.age=age
}
var xiaoming=Person('xiaoming',20);//错误调用,xiaoming为undefined
var xiaoming=new Person('xiaoming',20)//正确调用,xiaoming是一个对象
xiaoming.constructor===Person//true

注意,任何对象都有构造函数,直接用大括号声明的对象其构造函数就是Object

var a={
    name: 'obj'
}
a.constructor===Object//true

通过一个构造函数,我们就可以创造出很多不同的对象,有时这些对象需要公共的方法,最简单的方式是将方法直接放在构造函数中,但这样会造成内存的浪费:

function Person(name,age){
    this.name=name;
    this.age=age;
    this.sayhi=function(){
        console.log("hi,I'm "+this.name);
    }
}
var xiaoming=new Person('xiaoming',20);
var xiaogang=new Person('xiaogang',20);
xiaoming.sayhi===xiaogang.sayhi//false,两个对象的公共函数不是用的同一份代码

2.原型对象

什么是原型对象?

JS中的所有对象,不管是用构造函数的方法创建的,还是直接用大括号创建的

都有一个_proto_ 属性指向它的原型对象,该原型对象有一个constructor属性指向它的实例对象的构造函数

有一个constructor属性指向它的构造函数,该构造函数有一个prototype属性指向它的原型对象

有点绕,画成图就是这个样子,从图中可以看出上面所说的各个属性的取值

再用代码来表示

function Person(name,age){
    this.name=name;
    this.age=age
}
var xiaoming=new Person('xiaoming',20)//
xiaoming.constructor===Person
//true,实例对象的constructor属性指向构造函数

Person===xiaoming.__proto__.constructor
//true,原型对象的constructor属性指向构造函数

xiaoming.__proto__===Person.prototyp;
//true,构造函数的prototype属性和实例对象的__proto__属性都只想原型对象

var xiaohong=new Person('xiaohong',20)
xiaohong.__proto__===xiaoming.__proto__;
//true,不同实例对象的原型对象是同一个

由此得出,xiaoming.__proto__属性和Person.prototype属性所指向的,就是由构造函数Person创建出的所有对象所共有的原型对象,那么只要将公共方法作为这个原型对象的方法,就可以实现一个方法供不同的实例对象调用

Person.prototype.sayHi=function(){
    console.log("Hi,I'm "+this.name);
}
xiaoming.sayHi()//Hi,I'm xiaoming
xiaohong.sayHi()//Hi,I'm xiaohong
xiaoming.sayHi===xiaohong.sayHi///true,是同一个函数

3.原型链

现在我们知道,xiaoming的_proto_属性指向它的原型对象,而事实上,它的原型对象也有_proto__属性,指向它的原型对象

xiaoming.__proto__.__proto__//Object
xiaoming.__proto__.__proto__.__proto__//null
xiaoming.__proto__.__proto__.__proto__.__proto__//出错,null没有原型对象,也就没有__proto__属性

像这样,一个个的对象和原型对象串在一起,以实例对象为起点,以没有原型对象的null为终点,就组成了原型链。

上面我们将sayHi方法绑定到xiaoming的原型对象上,并且对象xiaoming可以调用该函数,那么是不是说sayHi是xiaoming自身的属性呢?我们用hasOwnProperty()方法来检验一下

xiaoming.hasOwnProperty('sayHi')//false
xiaoming.hasOwnProperty('sayhi')//true

可见,在构造函数内定义的函数sayhi是xiaoming自身的属性,而定义在原型对象上的函数sayHi则不是,那么为什么xiaoming可以调用该方法呢?

这是因为在JS中,调用一个对象的属性时,如果该对象自身没有这个属性,那么就会自动在它的原型对象上找,若还没有则顺着原型链往上找,若直到某一原型对象的原型对象为null,仍未找到,则会返回错误。也就是说,对象会继承其原型对象的属性

总结

  1. 对象都有构造函数,或是默认构造函数,或是自己写的构造函数
  2. 实例对象的__proto__属性指向其原型对象,constructor属性指向构造函数
  3. 构造函数的prototype属性指向原型对象,原型对象的constructor属性指向构造函数
  4. 实例对象->原型对象->原型对象的原型对象->…->null组成了原型链,对象会继承原型链上所有原型对象的属性
  5. 查找某一对象的某一属性时,若该对象自身没有该属性则会顺着原型链往上找,直到原型链的末尾
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值