new的作用
function Fruit(name){
this.name = name;
}
Fruit.prototype.show = function(){
console.log(this.name);
}
var banana = new Fruit('banana');
//輸出Fruit.protoype
console.log(Object.getPrototypeOf(banana));
//輸出Fruit.prototype
console.log(banana.__proto__);
//輸出'banana'
console.log(banana.show());
//輸出'banana'
console.log(banana.name);
//輸出true
console.log(banana.hasOwnProperty("name"));
//輸出false
console.log(banana.hasOwnProperty("show"));
可以看到毕籽,經(jīng)過new之后返回了一個對象兽愤,該對象的構(gòu)造函數(shù)原型為Fruit.prototype,也就是proto指向Fruit.prototype
并且banana可以調(diào)用show和name屬性,但name是其擁有的屬性,show是原型上的屬性胀屿。
也就是new做了以下幾件事
- 返回一個對象,該對象的proto指向構(gòu)造函數(shù)的原型
- 該對象會實現(xiàn)構(gòu)造函數(shù)中的實例屬性揭鳞,也就是調(diào)用構(gòu)造函數(shù)的apply方法
初步實現(xiàn)new操作符
function objectFactory(paramConstrutor){
if(typeof paramConstrutor !== 'function' ){
throw new Error("");
}
var args = Array.prototype.slice.call(arguments,1);
//設(shè)置obj的proto為constructor的proto,也就是繼承共享屬性
//兩種方式逛拱,
//一種是直接設(shè)置__proto__,官方不建議,后面可能變成只讀屬性
var obj = new Object();
obj.__proto__ = paramConstrutor.prototype;
//一種是通過Object.create()或者該方式的polyfill
//模擬Object.create()
function Empty(){};
Empty.prototype = paramConstructor.prototype;
var obj = new Empty();
//繼承實例屬性
paramConstructor.apply(obj,args);
return obj;
}
如果構(gòu)造函數(shù)由返回值滴须,那應(yīng)該是返回新建的對象還是返回值呢舌狗?
- 直接返回返回值,當返回值是Object扔水、Function痛侍、Array、Date、RegExg主届、Error
- 返回新建對象赵哲,當返回值是Null、Undefined君丁、Number枫夺、Boolean、String绘闷、Symbol
function Fruit(name){
this.name = name;
return {
a:1
}
}
var banana = new Fruit('banana');
//{a:1}
console.log(banana);
function Fruit(name){
this.name = name;
return 1;
}
var banana = new Fruit('banana');
//Fruit {name:'banana‘}
console.log(banana);
完整代碼
根據(jù)上面的返回值橡庞,進一步完善代碼。
需要了解的:
- typeof檢測除了Function之外的都為object
- typeof檢測Null為object
function objectFactory(paramConstructor){
if(typeof paramConstructor !== 'function'){
throw new Error("");
}
var args = Array.prototype.slice.call(arguments,1);
//繼承共享屬性印蔗,修改proto屬性
function Empty(){};
Empty.prototype = paramConstructor.prototype;
var obj = new Empty();
//繼承實例屬性
var result = paramConstructor.apply(obj,args);
var isObejct = typeof result === 'object' && result !== null;
var isFunction = typeof result === 'function';
if(isObejct ||isFunction ){
return result
}
return obj;
}