New的原理

😾 New的原理

new 关键词的主要做用就是执行一个构造函数、返回一个实例对象,在 new 的过程当中,根据构造函数的状况,来肯定是否能够接受参数的传递。下面咱们经过一段代码来看一个简单的 new 的例子

🍊 new的执行过程

new 操做符能够帮助咱们构建出一个实例,而且绑定上 this,内部执行步骤可大概分为如下几步:
  • 📕 建立一个新对象
  • 📕 对象链接到构造函数原型上,并绑定 this(this 指向新对象)
  • 📕 执行构造函数代码(为这个新对象添加属性)
  • 📕 返回新对象

例外

若是不用 new 这个关键词,结合上面的代码改造一下,去掉 new,会发生什么样的变化呢?咱们再来看下面这段代码
// 'use strict';

function Person() {
    this.name = "江小白";
}

var p = Person();
console.log(p); //undefined
console.log(name) //江小白
console.log(p.name); // Cannot read property 'name' of undefined
  • 📔 从上面的代码中能够看到,咱们没有使用 new 这个关键词,返回的结果就是 undefined。其中因为 JavaScript 代码在默认状况下 this 的指向是 window,那么 name 的输出结果就为江小白,这是一种不存在 new 关键词的状况。
  • 📔 那么当构造函数中有 return 一个对象的操做,结果又会是什么样子呢?咱们再来看一段在上面的基础上改造过的代码。
function Person() {
    this.nem = "江小白";
    return { age: 22 };
}

var p = new Person();
console.log(p); //{ age: 22 }
console.log(p.name); //undefined
console.log(p.age); //22

经过这段代码又能够看出,当构造函数最后 return 出来的是一个和 this 无关的对象时,new 命令会直接返回这个新对象,而不是经过 new 执行步骤生成的 this 对象app

可是这里要求构造函数必须是返回一个对象,若是返回的不是对象,那么仍是会按照 new 的实现步骤,返回新生成的对象。接下来仍是在上面这段代码的基础之上稍微改动一下函数

function Person(){
   this.name = '江小白'; 
   return 'tom';
}
var p = new Person(); 
console.log(p)  // {name: '江小白'}
console.log(p.name) // 江小白
💝 所以咱们总结一下: new 关键词执行以后老是会返回一个对象,要么是实例对象,要么是 return 语句指定的对象

✏️ 手写实现new

//  手写模拟new
function myNew(fn, ...args) {
    if (typeof fn !== 'function') {
        throw 'fn mast be a function';
    }
    // 1. 用new Object()建立一个对象obj
    var obj = new Object();
    // 2. 给该对象的__proto__赋值为fn.prototype,即设置原型链
    obj.__proto__ = Object.create(fn.prototype);
    // 3. 执行fn,并将obj做为内部this。使用 apply,
    // 改变构造函数 this 的指向到新建的对象,
    // 这样 obj 就能够访问到构造函数中的属性
    var result = fn.apply(obj, args); 
    // 4. 若是fn有返回值,则将其做为new操做返回,不然返回obj
    return result instanceof Object ? result : obj;
}

🔖 test

// test 
function Person(...args) {
  console.log(args)
}
// 使用内置函数new
var person1 = new Person(1,2)
console.log(person1)
// 使用手写的new,即create
var person2 = myNew(Person, 1, 2)
console.log(person2)
new 被调用后大体作了哪几件事情
  • 📒 让实例能够访问到私有属性;
  • 📒 让实例能够访问构造函数原型(constructor.prototype)所在原型链上的属性;
  • 📒 构造函数返回的最后结果是引用数据类型。
相关文章
相关标签/搜索