模拟 JS new 运算符
1. JS new 运算符做了什么
- 操作对象仅能为函数
- 创建一个新对象
- 新对象的原型链指向函数的 prototype 属性
- 新对象绑定到函数的 this
- 若函数返回一个对象类型的值,则返回,反之返回新对象
操作对象仅能为函数
var arr = [1,2,3];
new arr;
// Uncaught TypeError: arr is not a constructor
// 大家可以试试别的类型
var fun = function () {};
new fun;
创建一个新对象
function fun() {}
var f = new fun;
console.log(typeof f);
// object
新对象的原型链指向函数的 prototype 属性
function fun() {}
var f = new fun;
console.log(f.__proto__ === fun.prototype);
console.log(Object.getPrototypeOf(f) === fun.prototype);
新对象绑定到操作函数的 this
function fun() { this.name = 'n'; }
var f = new fun;
console.log(f);
function fun1(name) { this.name = name; }
var f1 = new fun1('cheng');
console.log(f1);
若函数返回一个对象类型的值,则返回,反之返回新对象
function fun() { this.name = 'n'; return 123; }
var f = new fun;
console.log(f);
function fun0() { this.name = 'n0'; return null; }
var f0 = new fun0;
console.log(f0);
// 大家可以试试别的类型
function fun1() { this.name = 'n1'; return [123]; }
var f1 = new fun1;
console.log(f1);
2. 模拟 JS new 操作符
function myNew() {
var fun = arguments[0];
var arrParams = [].slice.call(arguments, 1);
// 操作对象仅能为函数
if (typeof fun !== 'function') {
throw new Error('first parameter must be a function')
}
// 创建一个新对象
// 新对象的原型链指向函数的 prototype 属性
var newObject = Object.create(fun.prototype);
// 新对象绑定到函数的 this
var result = fun.apply(newObject, arrParams);
// 若函数返回一个对象类型的值,则返回,反之返回新对象
if (result !== null &&
(typeof result === 'object') || (typeof result === 'function')){
return result;
}
else {
return newObject;
}
}
3. 测试所写的方法
操作对象仅能为函数
var arr = [1,2,3];
// new arr;
myNew(arr);
var fun = function () {};
// new fun;
myNew(fun);
创建一个新对象
function fun() {}
// var f = new fun;
// console.log(typeof f);
var f = myNew(fun);
console.log(typeof f);
// object
新对象的原型链指向函数的 prototype 属性
function fun() {}
// var f = new fun;
var f = myNew(fun);
console.log(f.__proto__ === fun.prototype);
console.log(Object.getPrototypeOf(f) === fun.prototype);
新对象绑定到操作函数的 this
function fun() { this.name = 'n'; }
// var f = new fun;
var f = myNew(fun);
console.log(f);
function fun1(name) { this.name = name; }
// var f1 = new fun1('cheng');
var f1 = myNew(fun1, 'cheng');
console.log(f1);
若函数返回一个对象类型的值,则返回,反之返回新对象
function fun() { this.name = 'n'; return 123; }
// var f = new fun;
var f = myNew(fun);
console.log(f);
function fun0() { this.name = 'n0'; return null; }
// var f0 = new fun0;
var f0 = myNew(fun0);
console.log(f0);
// 大家可以试试别的类型
function fun1() { this.name = 'n1'; return [123]; }
// var f1 = new fun1;
var f1 = myNew(fun1);
console.log(f1);
4. 总结
- 操作对象仅能为函数
- 创建一个新对象
- 新对象的原型链指向函数的 prototype 属性
- 新对象绑定到函数的 this
- 若函数返回一个对象类型的值,则返回,反之返回新对象
没注释的模拟方法
function myNew() {
var fun = arguments[0];
var arrParams = [].slice.call(arguments, 1);
if (typeof fun !== 'function') {
throw new Error('first parameter must be a function')
}
var newObject = Object.create(fun.prototype);
var result = fun.apply(newObject, arrParams);
if (result !== null &&
(typeof result === 'object') || (typeof result === 'function')){
return result;
}
else {
return newObject;
}
}