面试题:new一个函数发生了什么?

基础储备

构造函数-ES5

函数本身就是构造函数
当做类用的函数本身也是一个函数,而且他就是默认的构造函数。我们想让Person函数能够设置实例的姓名,只要让他接收参数就行了。

function Person(name) {
    this.name = name;
}

// 通过实例化可以传入对应参数
const setName = new Person("RainBow");

注意上面代码的this,被作为类使用的函数里面this总是指向实例化对象,也就是Person。

实例方法用prototype
上面我们实现了类和构造函数,但是类方法呢?JS给出的解决方案是给方法添加一个prototype属性,挂载在这上面的方法,在实例化的时候会给到实例对象。我们想要Person能说话,就需要往Person.prototype添加说话的方法。

Person.prototype.say = function(){
    console.log(`My name is ${this.name}`);
}

使用new关键字产生的实例都有类的prototype上的属性和方法,我们在Person.prototype上添加了say方法,Person就可以说话了,我么来试一下:

Person.say();    // Rainbow

ES6

  • 创建类实例 - 对象
  • 创建实例的时候执行构造函数
class Person {
    constructor(name) {
        console.log('constructor')
        this.name = name
    }
​
    say() {
        console.log('My name is ',this.name)
    }
}
const b = new Person("b");

new的作用分析

// Es5 构造函数
// TODO:2.构造函数被执行
function Person (name){
    // TODO:3.将构造函数的this指向新对象
    this.name = name;
}
// TODO:4.修改新对象的原型链
Person.prototype.say = function(){
    console.log(`My name is ${this.name}`);
}

const p = new Person('Lao wang');
p.say() // TODO: 结论 1.基础类型返回空对象 2.引用类型返回引用类型

模拟函数

/*
    new的模拟
        - fn,构造函数
        - args 执行构造函数的输入参数
*/ 
function myNew(fn,...args){
    // 1.创建一个空对象
    const obj = {};
    // 2.改原型,将该对象的__proto__属性链接到构造函数的原型对象
    obj.__proto__ = fn.prototype
    // 3.执行构造函数,将该对象作为this上下文调用构造函数并接收返回值
    const res = fn.apply(obj,args);
    // 4.返回对象
    return typeof res === 'object' ? res : obj;
}

面试攻略

  • 面型对象、原型链、apply如何绑定上下文分别解释清楚

猜你喜欢

转载自juejin.im/post/7066794892990611493