看完必会原型和原型链

231 阅读3分钟

前言

对于前端刚刚入门,原型和原型链算是一个难点而且比较绕,面试又基本肯定会问到,所以整理一版,便于自己回头总结和大家讨论。

一、构造函数

原型首先需要明白构造函数、实例原型、和实例之间的关系(不得不承认有点儿乱)

function Person() {

}
// 虽然写在注释里,但是你要注意:
// prototype是函数才会有的属性
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin

这是构造函数,构造函数有prototype上面的属性直接进行了赋值

创建了实例对象输出,最后输出(一般都没啥问题)

*一个构造函数可以生成多个实例

二、prototype属性

每个函数都有一个prototype属性(函数,函数,函数)

function Person() {

}
// 虽然写在注释里,但是你要注意:
// prototype是函数才会有的属性
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin

从上面可以看出,protype指向的是通过构造函数调用创建的实例对象,即prototype是person1和2的原型,每一个对象都会从原型中继承属性。

三、__proto__属性

每个javascript对象上都有一个__proto__属性(对象,对象,对象),该属性会指向该对象的原型。(即person1.proto === Person.prototype)

四、constructor属性

每一个原型都有一个constructor属性(原型,原型,原型),该属性指向该原型的构造函数(即Person === Person.prototype.constructor)

*需要注意的是,当person(小写)没有constructor属性时,他会在该对象的原型对象上去找,即person.constructor = Person.prototype.constructor

接下来就是面试中经常会问到或者笔试遇到的一些问题

五、实例与对象

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,直到找到最顶层为止。

function Person() {

}

Person.prototype.name = 'Kevin';

var person = new Person();

person.name = 'Daisy';
console.log(person.name) // Daisy

delete person.name;
console.log(person.name) // Kevin

第一个输出,打印的就是该对象本身属性;第二个输出,因为自己本身对象上并没有这个属性,就去找该对象的原型的属性,即Person.prototype的name属性,所以打印出来是原型的属性值。

六、原型的原型

原型对象也是对象,所以也可以用最原始的方法去创建他。

var obj = new Object();
obj.name = 'Kevin'
console.log(obj.name) // Kevin

即obj.proto === Objcet.prototype

Objcet.prototype.__proto === null 此处Objcet.prototype的原型指向null,即最初的Objcet.prototype没有原型即为最顶层了已经

七、原型链

本质上来说就是一个链表结构,即有属性(proto)值将各个节点(即原型对象,Function.prototype,Object.prototype)连接在了一起。

三个常用和容易混淆的原型链指向顶层(除对象外,都需要先指向自己的本身的原型对象,再指向Object的原型对象,适用于其他number类型,string类型等等)

obj -> Object.prototype -> null 即 obj.proto = Object.protype Object.protype.__proto === null

func -> Function.prototype -> Object.prototype -> null

arr -> Array.prototype -> Object.prototype -> null

八、补充instanceof,判定为true的条件即是在原型链上能找到对象的类型

举个例子:arr instanceof Array 输出为true 因为在arr的原型对象上能找到Array对象

​ arr instanceof Object 输出也为true,因为Array的原型指向Object,所以arr的原型链上也能找到Object所以为true

九、常见易错面试

上面说到,当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,直到找到最顶层为止。

const obj = {}

obj.x 直接输出肯定是undefined

但是在obj原型上挂一个属性后即Object.prototype.x === 'x'

obj.x 输出为x

最易出错的是

const func = () => {}

Object.prototypr.x === 'x'

func.x 输出为x

get到了么,最后一道常见面试题测试下吧

var foo = {},

​ F = function() {}

Object.prototype.a = 'value a';

Function.prototype.b = 'value b'

console.log(foo.a); console.log(foo.b); console.log(F.a); console.log(F.b)

答案:value a; undefined; value a; value b