一、是什么
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
1.1 语法
new constructor[([arguments])]
1.2 参数
constructor:一个指定对象实例的类型的类或函数arguments:一个用于被constructor调用的参数列表
举个栗子:
function Cat(name, age, color) {
this.name = name;
this.age = age;
this.color = color;
}
Cat.prototype.saying = function() {
console.log(this.name, "说:喵喵喵~")
};
let fulai = new Cat("福来", 0.6, "乳白");
console.log(fulai.name) // 福来
fulai.saying(); // 福来 说:喵喵喵~
从上面可得到:
new通过构造函数Cat创建出来的实例可以访问到构造函数中的属性new通过构造函数Cat创建出来的实例可以访问到构造函数原型链中的属性(即实例与构造函数通过原型链连接了起来)
function Cat1(name, age, color) {
this.name = name;
this.age = age;
this.color = color;
return "福来"
}
let fulai = new Cat1("福来", 0.6, "乳白");
console.log(fulai, fulai.name)
function Cat1(name, age, color) {
this.name = name;
this.age = age;
this.color = color;
return {
bieming: "zhangsam"
}
}
let fulai = new Cat1("福来", 0.6, "乳白");
console.log(fulai, fulai.name)
从上面两个示例可以发现:
- 构造函数中返回一个原始值,这个返回值并没有作用
- 构造函数如果返回值为一个对象,那么这个返回值会被正常使用,并且初始值没有作用
二、执行过程
通过上面的例子,我们可以了解到new关键字主要工作流程如下:
- 创建一个空的JavaScript对象
obj(即{}) - 将步骤1创建的对象添加属性
——proto——,将该属性链接至构造函数的原型对象 - 将步骤1创建的对象作为
this的上下文 - 如果该函数没有返回对象,则返回
this。(如果该构建函数返回类型是原始值则被忽略,如果是返回对象,需要正常处理)
function Person(name, age){
this.name = name;
this.age = age;
}
const person1 = new Person('Tom', 20)
console.log(person1) // Person {name: "Tom", age: 20}
t.sayName() // 'Tom'
流程图如下:
三、手写new操作符
/**
* 模仿new关键词实现
* @param {Func} constructor 构造函数
* @param {...args} argument 任意参数
*/
function mynew(Func, ...args) {
// 1. 创建一个新对象
const obj = {};
// 2.新对象原型指向构造函数原型对象
obj.__proto__ = Func.prototype;
// 3.将构造函数的this指向新对象
let result = Func.apply(obj, args)
// 4.根据返回值判断
return result instanceof Object ? result : obj;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
let zhangsan = mynew(Person, "张三", "25")
let lisi = new Person("李四", "35")
我们打印zhangsan和lisi:
zhangsan和lisi的原型对象: