1. 原型与原型链
1.1 什么是原型
对于任意一个引用类型, 都存在一个属性 [[Prototype]]
, 这就是我们所说的原型
而对于一个 function
, 在存在一个 [[Prototype]]
的基础上, 其还会存在一个 prototype
属性, 这个属性是做什么的呢?
function fn(name, gender) {
this.name = name
this.gender = gender
}
let obj = new fn("altria", "female")
console.log(Object.getPrototypeOf(obj) === fn.prototype) //=> true
// obj 的 [[Prototype]] === fn.prototype
由上面的代码, 我们可以发现一个规律: new
构造函数 Fn
所获得的对象 obj
, 有 obj
的原型等于 Fn.prototype
.
至此, 我们可以说: 一个实例对象的原型和相应构造函数的 prototype
是同一个对象
1.2 什么是原型链
let arr = [1, 2]
arr.push(3)
Array.prototype.val = 233
Object.prototype.v = 55555
console.log(arr) //=> [1, 2, 3]
/*(3) [1, 2, 3]
* 0: 1
* 1: 2
* 2: 3
* length: 3
* [[Prototype]]: Array(0)
* */
console.log(arr.val) //=> 233 (arr -> Array.prototype)
console.log(arr.v) //=> 55555 (arr -> Array.prototype -> Object.prototype)
console.log(arr.push === Array.prototype.push) //=> true (arr -> Array.prototype)
由上面的代码, 我们发现: 在 arr
中, 其并没有 push
方法与 val
属性, 反而倒是其原型 [[Prototype]]
上存在一个 push
方法和 val
属性
- 通过
arr.push
访问到的push
方法与Array.prototype.push
完全一样 - 通过
arr.val
所获取的值与Array.prototype.val
也是一模一样 - 通过
arr.v
所获得的值与Object.prototype.v
也一样
至此, 我们可以说: 当在一个对象 obj
中访问某一属性 x
时, 若 obj
对象身上并没有 x
属性, 则其会到 obj
的原型 [[Prototype]]
上去寻找, 若再没有找到, 则继续到上一级的原型上去找, 直到没有原型为止, 此时就会返回 undefined
这样一系列的原型连接起来, 就被称为原型链
1.3 JS 中的原型关系
2. new 的模拟实现
function new_re(Fn, ...args) {
let obj = Object.create(Fn.prototype)
// 创建一个原型为 Fn.prototype 的对象
let res = Fn.call(obj, ...args)
// 执行构造函数时, 将 this 指向新实例对象
return (typeof res === "object" && res != null || typeof res === "function") ? res : obj
// 若构造函数返回的结果为引用类型, 则 new 出来的结果为该引用类型
// 若构造函数返回的结果为基础类型, 则 new 出来的结果为 Fn 的实例对象
}
对 new_re
的测试
function fn(name, gender) {
this.name = name
this.gender = gender
}
function f(name, gender) {
this.name = name
this.gender = gender
return function() {}
}
let o1 = new fn("altria", "female")
let o2 = new f("berserker", "male")
let oo1 = new_re(fn, "altria", "female")
let oo2 = new_re(f, "berserker", "male")
console.log(o1) //=> fn {name: 'altria', gender: 'female'}
console.log(oo1) //=> fn {name: 'altria', gender: 'female'}
console.log(o2) //=> ƒ () {}
console.log(oo2) //=> ƒ () {}
标签:arr,name,gender,原型,new,prototype,模拟
From: https://www.cnblogs.com/suzukaze/p/prototype-new.html