JS中的原型及原型链

1.原型

什么是原型?

  • prototype:显式原型,每一个构造函数都有一个prototype属性,它是一个普通对象,这个对象的方法和属性都会被构造函数所拥有
  • __proto__: 隐式原型, 每一个引用类型(数组、函数、对象)都有一个__proto__属性,指向构造函数的原型对象
  • 扩展: 所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性

原型的作用:数据共享

1.1原型的数据共享

在构造函数内部添加say方法

 function Person(name) {
            this.name = name 
            this.say = function() {
                console.log('hello')
            }
        }
        // 实例化
        var p = new Person('小明')
        var p1 = new Person('小红')

        console.log(p.say === p1.say) //false

总结:不同实例上的同名方法是不相等的

实例两个相同业务的构造函数实在没有必要,通过把函数定义转移到构造函数外部来解决以上问题

function Person(name) {
	this.name = name
	this.say = say
}
function say() {
	console.log('hello')
}
// 实例化
 var p = new Person('小明')
 var p1 = new Person('小红')

 console.log(p.say === p1.say)//true

总结:通过把构造函数中say方法转移到外部,但是如果方法多了就要创建很多个全局函数。

在原型对象中添加say方法

 // Person构造函数
        function Person(name) {
            this.name = name 
        }
        // 在原型对象中添加say方法
        Person.prototype.say = function() {
            console.log('hello')
        }
        // 实例化
        var p = new Person('小明')
        var p1 = new Person('小红')

        console.log(p.say === p1.say) //true

总结:p和p1的say方法指向同一块内存,实现了数据共享,和上面在构造函数内部及外部创建对象相比就在性能方面就要好的多

1.2查找机制
 // Person构造函数
        function Person(name) {
            this.name = name 
            this.say = function() {
                console.log('构造函数中say方法')
            }
        }
        // 在原型对象中添加say方法
        Person.prototype.say = function() {
            console.log('原型对象中的say方法')
        }
        // 实例化
        var p = new Person('小明')
       
        p.say()

总结:在调用p.say方法时,首先会去实例对象上查找是否有这个方法,如果有即调用,如果没有则调用prototype对象中say方法。其实它的查找机制还远不止如此,这样我们可以引申出第二个概念----"原型链"

2.原型链

在2.2中可能有人会奇怪,为什么实例对象中如果没有,会去原型对象中找呢?
1. 首先我们知道实例对象中的__proto__是指向构造函数中prototype的,所以实例对象身上没有,才会去原型对象身上查找

这里又引申出来一个问题,如果原型对象身上也没有这个方法呢?

在上面原型的介绍中说了,prototype也是一个对象,而每一个对象中都__proto__对象,而所有对象中的__proto__都指向它的prototype,这样一层一层向上查找的的链式结构,被称为"原型链"

2.1 案列
// Person构造函数
        function Person(name) {
            this.name = name 
            this.say = function() {
                console.log('构造函数中say方法')
            }
        }
        // 实例化
        var p = new Person('小明')
        // 判断p实例对象是否有tostring方法
        var res = p.toString() ? true : false
        console.log(res)

这里我的实例对象和原型对象中都没有这个tostring方法,那这个方法是从那来的呢?
在这里插入图片描述

  • 首先Person是构造函数,p是实例对象,那么就有p.__proto__ === Person.prototype
  • 我们上面说到过,prototype是一个普通对象,它内部也有__proto__,并且指向Object.prototype,那么就得到了这层关系----Person.prototype.__proto__ === Object.prototype
  • 联系以上两点,我们知道了它会按照这个查找机制,直到为null为止

总结:当实例对象调用tostring方法时,发现在实例对象和原型对象上查找时并没有这个方法,于是通过Person.prototype查找,发现还是没有,再通过Person.prototype.__person__查找,最后在Object.prototype身上找到了这个tostring方法,之所以能按照这种机制找到tostring方法,就是因为原型链的存在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值