面试 JS 原型与原型链

我们先来了解下面引用类型的四个规则:
1、引用类型,都具有对象特性,即可自由扩展属性。
2、引用类型,都有一个隐式原型 proto 属性,属性值是一个普通的对象。
3、引用类型,隐式原型 proto 的属性值指向它的构造函数的显式原型 prototype 属性值。
4、当你试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 proto(也就是它的构造函数的显式原型 prototype)中寻找。

引用类型:Object、Array、Function、Date、RegExp。这里我姑且称 proto 为隐式原型。

把下面的图记下来原型链基本也就掌握了,对应的关系已经标的很明白了
在这里插入图片描述

代码演示

var M = function (name) {this.name = name}
M.prototype = {
	say: function() {
		console.log(this.name + '说你好!')
	}
}
var o1 = new M('o1')
// M为构造函数 o1为实例
console.log(M.prototype) // {constructor: {...}}
console.log(M.prototype.constructor === M) // true 
console.log(o1.__proto__ === M.prototype) // true
o1.say() // o1说你好 原型对象里定义的方法

每个函数(构造函数)都有一个prototype(显式原型)属性这个属性指向原型对象,实例有一个__proto__(隐式原型)指向实例构造函数的原型对象,这就是原型。
为何要使用原型
如果M.prototype里的say方法直接写在构造函数里频繁的去new就会造成资源浪费,而通过原型来实现的话,只需要在构造函数里面给属性赋值,而把方法写在M.prototype属性里面。这样每个对象都可以使用prototype属性里面的say方法,并且节省了不少的资源。
原型链

function Person(name) {
  this.name = name
  return this // 其实这行可以不写,默认返回 this 对象
}

var nick = new Person("nick")
nick.toString
// ƒ toString() { [native code] }

按理说, nick 是 Person 构造函数生成的实例,而 Person 的 prototype 并没有 toString 方法,那么为什么, nick 能获取到 toString 方法?

这里就引出 原型链 的概念了, nick 实例先从自身出发查找自己是否有这个方法,发现并没有 toString 方法。找不到,就往上走,找 Person 构造函数的 prototype 属性,还是没找到。构造函数的 prototype 也是一个对象嘛,那对象的构造函数是 Object ,所以就找到了 Object.prototype 下的 toString 方法。

那么 __proto__是用来干啥的呢?其实就是为了寻找原型对象的 属性 或者 方法,如果没找到会通过 proto(也就是它的构造函数的显式原型 prototype)中寻找,一直到null为止
proto寻找过程
总结

原型:每个函数(构造函数)都有一个prototype属性这个属性指向原型对象,实例有一个__proto__指向实例构造函数的原型对象,这就是原型

为何使用原型:当所有的实例对象都需要共享属性和方法时,通过原型来实现就是将属性方法放在 实例对象的构造函数 中的prototype属性中,可以节省资源。

原型链: 当你试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 proto(也就是它的构造函数的显式原型 prototype)中寻找,一直到null为止

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值