😾 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 对象
但是这里要求构造函数必须是返回一个对象,如果返回的不是对象,那么还是会按照 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)所在原型链上的属性;
- 📒 构造函数返回的最后结果是引用数据类型。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。