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)過(guò)new之后返回了一個(gè)對(duì)象,該對(duì)象的構(gòu)造函數(shù)原型為Fruit.prototype,也就是proto指向Fruit.prototype
并且banana可以調(diào)用show和name屬性,但name是其擁有的屬性,show是原型上的屬性。
也就是new做了以下幾件事
- 返回一個(gè)對(duì)象,該對(duì)象的proto指向構(gòu)造函數(shù)的原型
- 該對(duì)象會(huì)實(shí)現(xiàn)構(gòu)造函數(shù)中的實(shí)例屬性,也就是調(diào)用構(gòu)造函數(shù)的apply方法
初步實(shí)現(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;
//一種是通過(guò)Object.create()或者該方式的polyfill
//模擬Object.create()
function Empty(){};
Empty.prototype = paramConstructor.prototype;
var obj = new Empty();
//繼承實(shí)例屬性
paramConstructor.apply(obj,args);
return obj;
}
如果構(gòu)造函數(shù)由返回值,那應(yīng)該是返回新建的對(duì)象還是返回值呢?
- 直接返回返回值,當(dāng)返回值是Object、Function、Array、Date、RegExg、Error
- 返回新建對(duì)象,當(dāng)返回值是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ù)上面的返回值,進(jìn)一步完善代碼。
需要了解的:
- typeof檢測(cè)除了Function之外的都為object
- typeof檢測(cè)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();
//繼承實(shí)例屬性
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;
}