📕 重学JavaScript:如何实现一个new
?
嗨,大家好!这里是道长王jj
~ 🎩🧙♂️
看过之前的文章的朋友应该都知道了实例对象和构造对象的关系
这个new
其实就是一个关键字,它可以让我们创建一个对象,并把它绑定到一个构造函数上。
比如,我们可以用new来创建一个名字叫Tom的人:
function Person(name) {
this.name = name;
this.sayHello = function() {
console.log(`Hello, I am ${
this.name}`);
};
}
// 使用new关键字,创建一个名字叫Tom的人
let tom = new Person("Tom");
// Hello, I am Tom
tom.sayHello();
那么,如何实现一个new的效果呢?
🔰 思路分析
想要知道new
怎么实现,首先我们得知道它这个过程中,干了些什么事情。
让实例可以访问到私有属性,也就是构造函数里用this添加的属性
比如,
this.name = name
就是给实例添加了一个私有属性name。👌让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性,也就是构造函数和其他对象共享的属性和方法。
比如,
Person.prototype.sayHello = function() {…}
就是给Person构造函数的原型对象添加了一个共享方法sayHello
。👌判断构造函数返回的结果
- 不是引用数据类型,那么就返回实例本身。
- 是引用数据类型,那么就返回这个引用数据类型
确定好思路之后,我们就可以进行伪代码环节了。
💫 伪代码思路
1. 创建一个空对象obj
2. 把obj的原型链指向构造函数的原型对象。p1.__proto__ = Person.prototype;
3. 把obj作为this参数传给构造函数,并执行构造函数。constructor.call(obj, ...args);
4. 如果返回值result是引用数据类型,就返回result,否则返回obj
⭕ 代码实现
function myNew(constructor, ...args) {
// 步骤1:创建一个空对象obj
let obj = {
};
// 步骤2:把obj的原型链指向构造函数的原型对象
obj.__proto__ = constructor.prototype;
// 步骤3:把obj作为this参数传给构造函数,并执行构造函数,得到返回值result
let result = constructor.call(obj, ...args);
// 步骤4:如果返回值result是引用数据类型,就返回result,否则返回obj
return result instanceof Object ? result : obj;
}
💥 测试一下各种情况看看有没有问题
function Person(name) {
this.name = name;
this.sayHello = function() {
console.log(`Hello, I am ${
this.name}`);
};
}
// 使用myNew函数,创建一个名字叫Tom的人
let tom = myNew(Person, "Tom");
// Hello, I am Tom
tom.sayHello();
// true
console.log(Object.getPrototypeOf(tom) === Person.prototype);
function Animal(type, sound) {
this.type = type;
this.sound = sound;
if (type === "cat") {
return {
name: 'Bob'};
}
}
// 测试如果是引用数据类型
let dog = myNew(Animal, "dog", "woof");
// dog
console.log(dog.type);
// woof
console.log(dog.sound);
// true
console.log(Object.getPrototypeOf(dog) === Animal.prototype);
// 测试如果不是引用数据类型
let cat = myNew(Animal, "cat", "meow");
// Bob
console.log(cat.name);
// undefined
console.log(cat.type);
// undefined
console.log(cat.sound);
// true
console.log(Object.getPrototypeOf(cat) === Object.prototype);
🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨