參考http://www.itdecent.cn/p/dee9f8b14771
js萬(wàn)物皆對(duì)象, 對(duì)象包括普通對(duì)象和函數(shù)對(duì)象(構(gòu)造器對(duì)象)
- 1 構(gòu)造器對(duì)象也就是函數(shù)對(duì)象, 如
var Person = function(){}
//生成方式
Person在生成時(shí), 會(huì)隱式使用如下方式
new Function('person', 'function(){}')
生成, 而Function.prototype會(huì)將自己引用到Person.__proto__上,
so
Person.__proto__ === Function.prototype
包括其他如Object, Array, 只要是函數(shù)對(duì)象, 它們的 __ proto __ 都是Function.prototype
console.log(Object.__proto__ === Function.prototype);
console.log(Function.__proto__ === Function.prototype);
//Function.prototype = new Function();
console.log(typeof Function.prototype);//funciton
//Array.prototype = new Object();普通對(duì)象
console.log(typeof Array.prototype);//object;
通過(guò)在Array.prototype這個(gè)普通對(duì)象上定義各種方法, 如map reduce sort等
由此可以看出Function.prototype是Function,
其他的都是object,
所以可以看做是一個(gè)普通的object對(duì)象
- 2 普通對(duì)象是通過(guò)函數(shù)對(duì)象new出來(lái)的, 然后在將函數(shù)對(duì)象(構(gòu)造器)的prototype屬性(就是一個(gè)普通對(duì)象)賦給普通對(duì)象的__ proto __, 這樣普通對(duì)象就可以調(diào)用構(gòu)造器prototype上的所有方法, 如:
var Person = function(name){
this.name = name;
}
//如果不定義他的原型, 默認(rèn)只是一個(gè)包含屬性constructor構(gòu)造函數(shù)的普通對(duì)象
//這里給Person.prototype定義一個(gè)eat屬性
Person.prototype.eat = function(){
console.log('eat');
console.log(this.name);
};
var tom = new Person('tom');
//在生成tom時(shí), 步驟如下
//(1)創(chuàng)建一個(gè)空對(duì)象var obj = {}
//(2)Person.apply(obj,arguments)
//apply其實(shí)是Function.prototype定義的方法
// 會(huì)讓Person()函數(shù)內(nèi)部的this指向obj,
所以你寫(xiě)的this.name就相當(dāng)于obj.name1。給對(duì)象添加屬性.
//(3)obj.__proto__ === Person.prototype // 搭建原型鏈
//這一步這是tom可以調(diào)用eat方法的關(guān)鍵
//(4)return obj;
// 讓var tom = new Person();中的tom接收obj,也就是這里的tom就是函數(shù)內(nèi)部的obj
tom.eat();//eat
總結(jié):
除Function.prototype為Function(因?yàn)镕unction.prototype = new Function),
其他所有構(gòu)造器對(duì)象的prototype都是一個(gè)普通的object, 可以給這個(gè)object定義不同的屬性, 然后通過(guò) new 構(gòu)造器 生成普通對(duì)象, 會(huì)搭建原型鏈, 即
var tom = new Person();
tom.__proto__ = Person.prototype
tom就能使用Person.prototype上所有的方法, 由于Person.prototype只是個(gè)普通的object對(duì)象(通過(guò)Person生成, 包含constructor屬性, 所以
Person.prototype.constructor = Person;
Person.prototype.__proto__ = Object.prototype
console.log(Object.getOwnPropertyNames(Object.prototype));
Object.prototype對(duì)象上的方法包括如下:

所以tom能使用Object.prototype的所有方法
Object.prototype.__proto__ = null;
Function.prototype為Function, 當(dāng)執(zhí)行
var Person = function(){}
搭建原型鏈時(shí)會(huì)將Function.prototype賦給Person.__ proto __屬性, ,而Function.prototype是一個(gè)Function, 包含的屬性值:

所以Person的call方法來(lái)源于Funciton.prototype.call, 可以直接調(diào)用Person()