new的作用
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
new的工作流程:
- 创建一个新对象
- 将新对象的proto指向构造函数【将空对象的原型指向构造函数】
- 构造函数的this指向空对象上
- 执行构造函数,如果返回值是对象那么返回这个实例对象,否则返回新对象。
function myNew(constructor,...arg){
if(typeof constructor !== 'function'){
throw new TypeError('类型错误')
}
// 定义一个对象
let newObj = {};
// 为 新创建的对象添加属性**__proto__**,将该属性链接至构造函数的原型对象
newObj.__proto__ = constructor.prototype;
// 前两行可以用 let newObj = Object.create(constructor.prototype);替换
// 新创建的对象作为 this 的上下文
const thisObj = constructor.call(newObj,...arg)
// 判断当前结果是对象还是函数
const isObject = typeof thisObj === 'object' && thisObj !== null;
const isFunction = typeof thisObj === 'function';
// 如果是对象或者函数返回构造函数的实例对象,否则返回新对象
return isObject || isFunction ? thisObj : newObj;
}
测验
function Car() {
this.name = '红旗'
}
Car.prototype.color = "original color";
const obj = myNew(Car)
console.log(obj.color)
帮助理解
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
const person1 = new Person('Tom', 20)
console.log(person1) // Person {name: "Tom", age: 20}
t.sayName() // 'Tom
从上面可以看到:
new通过构造函数Person创建出来的实例可以访问到构造函数中的属性,可以访问到构造函数原型链中的属性(即实例与构造函数通过原型链连接了起来)
现在在构建函数中显式加上返回值,并且这个返回值是一个原始类型
function Test(name) {
this.name = name
return 1
}
const t = new Test('xxx')
console.log(t.name) // 'xxx'
可以发现,构造函数中返回一个原始值,然而这个返回值并没有作用
下面在构造函数中返回一个对象
function Test(name) {
this.name = name
console.log(this) // Test { name: 'xxx' }
return { age: 26 }
}
const t = new Test('xxx')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'
从上面可以发现,构造函数如果返回值为一个对象,那么这个返回值会被正常使用