new
运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
语法:
new constructor[([arguments])]
示例:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name);
};
}
Person.prototype.sayHi = function () {
console.log('I am ' + this.name);
};
var person1 = new Person('xiaoming', 18);
console.log(person1.name); // xiaoming
console.log(person1.age); // 18
person1.sayName(); // xiaoming
person1.sayHi(); // I am xiaoming
console.log(person1 instanceof Person); //true
可以看到,使用new
操作符后,返回了一个新对象,这个对象是new操作符后面的构造函数的实例。
该对象可以访问构造函数的属性和方法,也可以访问构造函数原型上的属性和方法。
在使用new运算符调用构造函数时的执行过程:
1.创建一个新对象
2.将构造函数中的this指向该对象
3.执行构造函数代码(给新对象添加属性和方法)
4.返回者着新对象
据此,我们初步实现模拟new
的newTest
方法:
function myNew() {
// 创建空对象
var obj = {};
// 第一个参数是构造函数
var Constructor = [].shift.apply(arguments);
// 将新对象的内部属性__proto__指向构造函数的原型,这样新对象就可以访问原型中的属性和方法
obj.__proto__ = Constructor.prototype;
// 不推荐直接更改__proto__,可使用Object.create()来创建对象
// var obj = Object.create(Constructor.prototype);
// 使用apply,将构造函数中的this指向新对象,这样新对象就可以访问构造函数中的属性和方法
Constructor.apply(obj, arguments);
return obj;
}
var person1 = myNew(Person, 'xiaoming', 18); // 测试通过
一般情况下,构造函数是没有返回值的。
如果返回值是基本类型:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name);
};
return 'xiaoming';
}
Person.prototype.sayHi = function () {
console.log('I am ' + this.name);
};
var person1 = new Person('xiaoming', 18);
console.log(person1.name); // xiaoming
console.log(person1.age); // 18
person1.sayName(); // xiaoming
person1.sayHi(); // I am xiaoming
如果返回值是一个对象:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name);
};
return { name: 'xiaoming'};
}
Person.prototype.sayHi = function () {
console.log('I am ' + this.name);
};
var person1 = new Person('xiaoming', 18);
console.log(person1.name); // xiaoming
console.log(person1.age); // undefined
person1.sayName(); // Uncaught TypeError: person1.sayName is not a function
person1.sayHi();
可以看出:
当返回基本类型时,new constructor[([arguments])]
相当于没有返回值时进行处理;
当返回一个对象时,只能访问构造函数返回的对象的属性和方法。
据此,我们对之前的myNew
方法进行改进:
function myNew() {
// 创建空对象
var obj = {};
// 第一个参数是构造函数
var Constructor = [].shift.apply(arguments);
// 将新对象的内部属性__proto__指向构造函数的原型,这样新对象就可以访问原型中的属性和方法
obj.__proto__ = Constructor.prototype;
// 不推荐直接更改__proto__,可使用Object.create()来创建对象
// var obj = Object.create(Constructor.prototype);
// 使用apply,将构造函数中的this指向新对象,这样新对象就可以访问构造函数中的属性和方法
var ret = Constructor.apply(obj, arguments);
return typeof ret == 'object' ? ret : obj;
}
var person1 = myNew(Person, 'xiaoming', 18); // 测试通过