function Person() {
this.x = 1
}
Person.prototype.y = 2
var person = new Person()
console.log(person.x) //1 在 person 对象中有私有属性 x ,所以可以直接打印出结果 1
console.log(person.y) //2 在 person 对象中并没有名为 y 的属性,所以需要沿着原型链查找到 person.__proto__ (也就是 Person.prototype) 上,此时发现了名为 y 的属性,打印出结果2
console.log(person.z) //undefined 在原型链上没有名为 z 的属性,所以只能打印出 undefined
new 的执行过程及相应模拟
function Foo() {...}
let f1 = new Foo() // 与 let f1 = new Foo 的效果一样
原型与原型链及 new 的模拟实现
原型与原型链
1.原型的基本概念:
每个函数都有一个
prototype
,对函数使用new
操作符构造出的对象其__proto__
指向该构造函数的prototype
每个对象都有一个
__proto__
,每个对象的__proto__
均为其构造函数的prototype
,而构造函数的__proto__
则为Function.prototype
Object.prototype
是所有对象直接或间接的__proto__
指向正常情况下,每个
prototype
原型都有一个constructor
属性指向与之相关的构造函数2.实例与原型的关系:
当读取实例的属性时,如果无法直接在实例对象中找到该属性,则会寻找到该对象的
__proto__
上,如果找到了该属性,则返回该属性的值,而如果还找不到,则会沿着该__proto__
的__proto__
继续向上查找……如果一直找到Object.prototype
上也没有该属性的话,则返回undefined
new 的执行过程及相应模拟
new 的执行过程
形成一个新的执行上下文 EC
创建一个对象,并将 this 指向这个对象(该对象就是当前类的实例)
形成一个 AO 变量对象,并开始预编译
初始化作用域链 <AO, [[scope]]>
代码执行
如果构造函数
return
的是引用类型值,[new] 返回的就是构造函数 return 的引用类型值而如果构造函数
return
的是基本类型值,那么 [new] 就会返回新创建的实例对象new 的模拟实现