前端开发系列038-基础篇之new关键字
本文介绍JavaScript 语言中 new 关键字调用构造函数的内部执行细节和模拟实现。
在 JavaScript 语言中,我们通过 new
关键字来调用构造函数以创建实例对象,或者是通过 new
关键字来调用类以实例化,class
是ES6新增的特性,可以理解为它和构造函数是一样的。
在下面的代码中,我们先提供了构造函数Person
,然后设置原型对象并创建了实例对象 p。
/* 01-提供构造函数 */
function Person(name, age) {
this.age = age;
this.name = name;
this.showName = function() {
console.log("姓名:" + this.name);
}
this.showAge = function() {
console.log("年龄:" + this.age);
}
}
/* 02-设置原型对象 */
Person.prototype.showInfo = function() {
this.showName();
this.showAge();
}
/* 03-创建实例对象 */
let p = new Person("Yong", 16);
/* 04-测试代码 */
console.log(p);
p.showInfo();
/* 打印输出结果:
Person {
age: 16,
name: 'Yong',
showName: [Function],
showAge: [Function]
}
姓名:Yong
年龄:16
*/
构造函数的代码如果换成是Class,那结果也是一样的。这里我们需要关注下当使用 new 关键字
来调用构造函数或者类的时候都做了些什么,也就是内部的实现细节,下面通过代码注释的方式来对这些细节进行说明。
/* 01-提供构造函数 */
function Person(name, age) {
/* [1] 创建空对象 */
/* 模拟:let o = {} */
/* [2] 设置原型对象访问 */
/* 模拟:o.__proto__ = Person.prototype; */
/* [3] 修改 this 指向空对象 */
/* 模拟:this = o */
/* [4] 通过 this 来设置实例属性 */
this.age = age;
this.name = name;
/* [5] 通过 this 来设置实例方法 */
this.showName = function() {
console.log("姓名:" + this.name);
}
this.showAge = function() {
console.log("年龄:" + this.age);
}
/* [6] 默认总是返回内部新创建的对象(this) */
/* 如果主动 return , 若跟的是引用类型则直接返回,值类型则忽略 */
/* 模拟:return this */
}
/* 02-设置原型对象 */
Person.prototype.showInfo = function() {
this.showName();
this.showAge();
}
/* 03-创建实例对象 */
let p = new Person("Yong", 16);
最后,再花点时间来封装个函数以模拟new 关键字
的功能,列出给定代码和测试数据。
/* 01-模拟 new 关键字 */
function mockNew() {
/* [1]-获取构造器 */
/* 说明:arguments类数组执行删除操作,接收删除后的元素 */
let Constructor = [].shift.call(arguments);
/* [2]-创建空对象 */
let o = {};
/* [3]-设置新对象的原型指向构造函数的原型对象 */
/* 注意:默认 o.__proto__ 指向的是 Object.prototype */
o.__proto__ = Constructor.prototype;
/* [4] 把剩余的参数传递给构造函数(class) */
/* 关键:执行函数Constructor(arguments),并绑定内部的 this */
let instance = Constructor.apply(o, arguments);
/* [5] 处理返回值 */
/* 说明:如果是引用类型的数据那么就直接返回,否则总是返回内部新创建的对象 o */
return instance instanceof Object ? instance : o;
}
/* 02-提供构造函数(首字母大写区分) */
function Person(name, age) {
this.age = age;
this.name = name;
this.showName = function() {
console.log("姓名:" + this.name);
}
this.showAge = function() {
console.log("年龄:" + this.age);
}
}
/* 03-设置原型对象 */
Person.prototype.showInfo = function() {
this.showName();
this.showAge();
}
/* 04-测试代码 */
let p1 = mockNew(Person, "Yong", 16);
let p2 = mockNew(Person, "Yi", 18);
console.log(p1, p2);
// Person { age: 16, name: 'Yong', showName: [Function], showAge: [Function] }
// Person { age: 18, name: 'Yi', showName: [Function], showAge: [Function] }
p1.showInfo();
/* 姓名:Yong 年龄:16 */