Open hzzzzzzzq opened 2 years ago
new 操作,我们在类对象,函数中都会使用到,那么它到底是用来干什么的呢?又是怎么实现的呢?
我们先看看 MDN 的定义:
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
我们先来举个例子吧
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.weight = 70; Person.prototype.getInfo = function () { console.log(this.name, this.age, this.weight); }; const person = new Person('hzzzzzzzq', 18); console.log(person.name); // hzzzzzzzq console.log(person.age); // 18 console.log(person.weight); // 70 person.getInfo(); // hzzzzzzzq 18 70
我们从例子中来看,我们创建的实例 person 可以做到
所以由此我们来推断 new 操作做了什么。
但是由于 new 操作是关键字,所以就是用一个创建方法 objectFactory 来替代了。
new
objectFactory
let pserson = new Person(...arguments); // 等价我们创建的方法 let person = objectFactory(Person, ...arguments);
由此,我们来看第一版代码吧。
function objectFactory() { const obj = {}; // 创建一个新对象,也可以使用 new Object() const Constructor = [].shift.call(arguments); // 获取构造函数,传入参数的第一个值 obj.__proto__ = Constructor.prototype; // 将对象的原型指向构造函数的原型 Constructor.apply(obj, arguments); // 绑定对象,为对象添加属性 return obj; // 返回对象 }
接下来,我们来测试一下
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.weight = 70; Person.prototype.getInfo = function () { console.log(this.name, this.age, this.weight); }; function objectFactory() { const obj = {}; // 创建一个新对象,也可以使用 new Object() const Constructor = [].shift.call(arguments); // 获取构造函数,传入参数的第一个值 obj.__proto__ = Constructor.prototype; // 将对象的原型指向构造函数的原型 Constructor.apply(obj, arguments); // 绑定对象,为对象添加属性 return obj; // 返回对象 } // const person = new Person('hzzzzzzzq', 18); const person = objectFactory(Person, 'hzzzzzzzq', 18); console.log(person.name); // hzzzzzzzq console.log(person.age); // 18 console.log(person.weight); // 70 person.getInfo(); // hzzzzzzzq 18 70
发现,结果是一样的,这样就实现了吗? 当然不是,我们的构造函数如果有返回值呢?那会怎么样呢?
我们来看看例子,由此,我们可以看见,如果构造函数带有返回值,则会导致返回值以外定义的值无效。
function Person(name, age) { this.weight = 70; return { name: name, age: age, }; } Person.prototype.getInfo = function () { console.log(this.name, this.age, this.weight); }; const person = new Person('hzzzzzzzq', 18); console.log(person.name); // hzzzzzzzq console.log(person.age); // 18 console.log(person.weight); // undefined person.getInfo(); // TypeError: person.getInfo is not a function
但是返回值就一定是对象吗?结果显然是不一定。
所有,我们来看看不是对象时是什么情况:
function Person(name, age) { this.name = name; this.age = age; this.weight = 70; return 'hello'; } const person = new Person('hzzzzzzzq', 18); console.log(person.name); // hzzzzzzzq console.log(person.age); // 18 console.log(person.weight); // 70
我们发现,都正确返回了,所以我们需要进行判断
接下来我们来更改我们的代码.
function objectFactory() { const obj = {}; const Constructor = [].shift.call(arguments); obj.__proto__ = Constructor.prototype; const result = Constructor.apply(obj, arguments); // 获取 返回值 return typeof result === 'object' ? result : obj; // typeof 进行判读 }
我们来小结一下 new 做的事情。
JavaScript
{}
__proto__
this
到此,我们就完美复刻出了 new 操作喽。
new 关键字
new 操作,我们在类对象,函数中都会使用到,那么它到底是用来干什么的呢?又是怎么实现的呢?
第一版 - 基础完成
我们先看看 MDN 的定义:
我们先来举个例子吧
我们从例子中来看,我们创建的实例 person 可以做到
所以由此我们来推断 new 操作做了什么。
但是由于
new
操作是关键字,所以就是用一个创建方法objectFactory
来替代了。由此,我们来看第一版代码吧。
接下来,我们来测试一下
发现,结果是一样的,这样就实现了吗? 当然不是,我们的构造函数如果有返回值呢?那会怎么样呢?
第二版 - 返回值
我们来看看例子,由此,我们可以看见,如果构造函数带有返回值,则会导致返回值以外定义的值无效。
但是返回值就一定是对象吗?结果显然是不一定。
所有,我们来看看不是对象时是什么情况:
我们发现,都正确返回了,所以我们需要进行判断
接下来我们来更改我们的代码.
小结
我们来小结一下 new 做的事情。
JavaScript
对象(即{}
)__proto__
,将该属性链接至构造函数的原型对象this
的上下文 ;this
。到此,我们就完美复刻出了
new
操作喽。