原型,原型链,手动实现new操作

231 阅读3分钟

原型

理解protoType, proto, constructor

原型链

面试题

  1. 概述构造函数,原型和实例的关系 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
  2. 原型链 那么我们让原型对象等于另一个实例的实例,此时原型对象将包含一个指向另一个原型的指针,相应的,另一个原型中也包含一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,如此层层递进,就构成实例与原型的链条。
  3. 也就是如图的蓝色这条线

new 基础

new 操作实现的功能

function Test(name) {
	this.name = name
}
Test.prototype.sayName = function () {
		console.log(this.name)
}
const t = new Test('yck')
console.log(t.name) // 'yck'
t.sayName() // 'yck'

通过以上例子可知

  • new 通过构造函数 Test 创建出来的实例可以访问到构造函数中的属性
  • new 通过构造函数 Test 创建出来的实例可以访问到构造函数原型链中的属性,也就是说通过 new 操作符,实例与构造函数通过原型链链接了起来

如果构造函数有 return,会有什么影响

返回原始值不会生效,返回对象会导致 new 操作符没有作用。

  1. 如果返回原始值
function Test(name) {
	this.name = name
	return 1
}
const t = new Test('yck')
console.log(t.name) // 'yck'

构造函数如果返回原始值(虽然例子中只有返回了 1,但是你可以试试其他的原始值,结果还是一样的),那么这个返回值毫无意义

  1. 返回对象
function Test(name) {
	this.name = name
	console.log(this) // Test { name: 'yck' }
	return { age: 26 }
}
const t = new Test('yck')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'

构造函数如果返回值为对象,那么这个返回值会被正常使用

总结:构造函数尽量不要返回值。因为返回原始值不会生效,返回对象会导致 new 操作符没有作用。

调用 new 时会发生什么?

  1. 生成一个新对象
  2. 链接到原型
  3. 绑定 this
  4. 返回新对象

手写 new 操作符

首先我们再来回顾下 new 操作符的几个作用

  • new 操作符会返回一个对象,所以我们需要在内部创建一个对象
  • 这个对象,也就是构造函数中的 this,可以访问到挂载在 this 上的任意属性
  • 这个对象可以访问到构造函数原型上的属性,所以需要将对象与构造函数链接起来
  • 返回原始值需要忽略,返回对象需要正常处理
function create(Con,...args) {
    // 首先函数接受不确定数量的参数,第一个参数为构造函数,其他参数为构造函数所用
    // 内部创建一个空对象
    let obj = {};
    // 因为obj需要访问到构造函数原型链上的属性,所以通过原型量将两者联系起来
    // 下面这两句的效果是一样的
    // obj.__proto__ = Con.prototype;
    Object.setPrototypeOf(obj,Con.prototype);
    // 将this指向obj对象
    let result = Con.call(obj, ...args);
    // 判断构造函数返回的是否是函数,如果不是,则返回obj,这样实现了,忽略构造函数返回原始值的操作
    return result instanceof Object ? result : obj;
}

function Test(name) {
    this.name = name;
}
let a = create(Test,'li');
console.log(a);

通过 new 的方式创建对象和字面量创建有什么区别

通过new Object的方式,会调用Object构造函数,但是字面量不会调用构造函数

在调用Object方法的过程中,涉及到,要在原型链上找到Object这个方法,然后生成调用函数的堆栈,执行完该函数后,还要释放堆栈,综上,字面量要比new方法效率高且简洁