关于前端:前端百题斩018从验证点到手撕new操作符

写该系列文章的初衷是“让每位前端工程师把握高频知识点,为工作助力”。这是前端百题斩的第18斩,心愿敌人们关注公众号“执鸢者”,用常识武装本人的头脑。

18.1 根底

new的作用是通过构造函数来创立一个实例对象,该实例与原型和构造函数之间的关系如下图所示:

18.2 new过程中产生了什么

当一个构造函数new的过程到底产生了什么?简要概述次要分为以下几个步骤:

  1. 一个新对象被创立;
  2. 该对象的__ proto __属性指向该构造函数的原型,即Fn.prototype;
  3. 将执行上下文(this)绑定到新创建的对象中;
  4. 如果构造函数有返回值(对象或函数),那么这个返回值将取代第一步中新创建的对象。

new真的做了这几步吗?秉承着“实际是测验真谛的唯一标准”的准则,上面将这几个关键点进行逐个验证。

function Fun() {
    this.a = 10;
    this.b = 20;
    this.method1 = () => {
        return this.a + this.b;
    }
    this.method2 = () => {
        return this;
    }
}

Fun.prototype = {
    method2: () => {
        console.log('原型上的method1被拜访');
    }
}

18.2.1 验证点1——新对象被创立

验证点1是新对象被创立,其实这个外面有两层含意:

  1. new之后返回的内容是一个对象
const fun = new Fun();
console.log(fun); //  { a: 10, b: 20, method1: [Function] }
console.log(typeof(fun)); // object

通过打印其内容,并通过typeof进行验证,其返回内容的确是一个对象。

  1. 每次返回的都是一个新创建的对象
const fun1 = new Fun();
const fun2 = new Fun();
console.log(fun1 === fun2); // false

通过创立两个实例,通过判断两个实例不相等,则证实的确每次返回的是一个新的对象。

18.2.2 验证点2——该对象可拜访原型上的属性和办法

验证点2是新创建的实例可拜访原型上的属性和办法,验证该关键点只须要拜访原型上的办法即可实现,若原型上的办法可能被失常拜访,则示意该验证点通过,负责不通过。

const fun3 = new Fun();
fun3.method3(); // 原型上的method3被拜访

通过验证,原型上的办法的确可能被拜访。

18.2.3 验证点3——this指向

验证this指向只须要将this指向打印进去即可。

const fun4 = new Fun();
console.log(fun4.method2()); // { a: 10, b: 20, method1: [Function], method2: [Function] }
console.log(fun4.method2() === fun4); // true

18.2.4 验证点4——构造函数有返回值的解决逻辑

一个函数的返回值能够有多种,例如:string、boolean、number、Object、function等,上面咱们验证一些内容,看构造函数有不同的返回值,其实例为何值。

  1. 返回值为string
function Fun() {
    this.a = 10;
    this.b = 20;
    return 'test';
}
Fun.prototype = {
    method: () => {
        console.log('原型上的method被拜访');
    }
}

const fun = new Fun();
console.log(fun); // { a: 10, b: 20 }

察看其最终后果,字符串没有没失常返回,返回值是一个新的实例。

  1. 返回值为Object
function Fun() {
    this.a = 10;
    this.b = 20;
    return {
        c: 30
    };
}
Fun.prototype = {
    method: () => {
        console.log('原型上的method被拜访');
    }
}

const fun = new Fun();
console.log(fun); // { c: 30 }

察看其后果,返回值是函数中返回的对象,则表征当构造函数返回值为对象时,会返回其对象,不返回实例化后的内容。

  1. 返回值为function
function Fun() {
    this.a = 10;
    this.b = 20;
    return function() {
        this.d = 40;
    };
}
Fun.prototype = {
    method: () => {
        console.log('原型上的method被拜访');
    }
}

const fun = new Fun();
console.log(fun); // [Function]

返回函数的成果和返回对象的成果统一。

通过一直尝试总结,能够得出以下论断:

  1. 构造函数的返回值为根本类型,其返回值是实例化后的对象,不受返回值的影响;
  2. 构造函数的返回值是援用类型,其返回值即为new之后的返回值。

18.3 实现一个new

介绍了这么多,曾经了解了new时产生的事件并通过了验证,上面就手动实现一个本人的new函数。

function myNew(Fn, ...args) {
    // 一个新的对象被创立
    const result = {};
    // 该对象的__proto__属性指向该构造函数的原型
    if (Fn.prototype !== null) {
        Object.setPrototypeOf(result, Fn.prototype);
    }

    // 将执行上下文(this)绑定到新创建的对象中
    const returnResult = Fn.apply(result, args);
    // 如果构造函数有返回值(对象或函数),那么这个返回值将取代第一步中新创建的对象。
    if ((typeof returnResult === 'object' || typeof returnResult === 'function') && returnResult !== null) {
        return returnResult;
    }
    return result;
}

小试牛刀

function Fun() {
    this.a = 10;
    this.b = 20;
}
Fun.prototype = {
    method: () => {
        console.log('原型上的method被拜访');
    }
}
const fun1 = new Fun();
console.log(fun1); // { a: 10, b: 20 }
const fun2 = myNew(Fun);
console.log(fun2); // { a: 10, b: 20 }

1.如果感觉这篇文章还不错,来个分享、点赞吧,让更多的人也看到

2.关注公众号执鸢者,与号主一起斩杀前端百题

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理