前言
相信大家都听过前端的三座大山:闭包,原型链,作用域,吾辈被压迫久已矣。而我一直觉得基础是进阶的前提,所以不能因为是基础就忽视他们。今天我就以我的方式讲讲原型链吧,希望大家能牢固地掌握原型链知识,接下来开始了~
百度一下,我就知道
先来看张图吧,据说是原型链最好的总结了。
看完我吐了~!!,不是怀孕,但是也离不远了。
prototype和__proto__
这两个东西到底是啥呢?
- prototype: 显式原型
- __ proto__: 隐式原型
什么叫法都有,管他的你懂我懂大家懂就好。原型翻译过来,你叫模板也可以啊,阿巴阿巴阿巴、
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayName = function() {
console.log(this.name)
}
console.log(Person.prototype) // { sayName: [Function] }
const person1 = new Person('小明', 20)
console.log(person1.__proto__) // { sayName: [Function] }
const person2 = new Person('小红', 30)
console.log(person2.__proto__) // { sayName: [Function] }
console.log(Person.prototype === person1.__proto__) // true
console.log(Person.prototype === person2.__proto__) // true
到这里其实还是好理解的,在上个图吧。大家可以一边看图一边输出嘛~
顺带一提这里这里new干了啥
模拟new
使用new时,到底发生了什么?
- 创建一个空对象,作为将要返回的对象实例
- 将这个空对象的原型,指向了构造函数的
prototype属性 - 将这个空对象赋值给函数内部的
this关键字 - 开始执行构造函数内部的代码
- 如果构造函数返回一个对象,那么就直接返回该对象,否则返回创建的对象
也就是说,构造函数内部,this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(即this对象),将其“构造”为需要的样子。
function simulateNew() {
let newObject = null,result = null,
constructor = Array.prototype.shift.call(arguments)
// 参数判断
if (typeof constructor !== 'function') {
console.error('type error')
return
}
// 新建一个空对象,对象的原型为构造函数的 prototype 对象
newObject = Object.create(constructor.prototype)
// 将 this 指向新建对象,并执行函数
result = constructor.apply(newObject, arguments)
// 判断返回对象
const flag =
result && (typeof result === 'object' || typeof result === 'function')
// 判断返回结果
return flag ? result : newObject
}
/** 测试如下 */
function Person(name) {
this.name = name
}
const p1 = new Person("p1")
const p2 = simulateNew(Person, 'p2')
console.log("p1",p1, p1 instanceof Person);
console.log('p2', p2, p2 instanceof Person)
复制代码
原型链是啥?
知道了这个new的时候,将这个空对象的原型,指向了构造函数的prototype属性,这句话就是重点,如果不理解有这个过程,你会发现这个小蝌蚪找爸爸的过程,不知道怎么找这个爸爸,为啥我要认这个爸爸?
最后附上三哥的文章推荐,写得很好。大家看不懂的地方他都解答了,然后最后的练习题也很好~