js中,萬物皆對象。對象分爲函數對象和普通對象。記住Object和Function是js自帶的函數對象。segmentfault
console.log(typeof Object); //function console.log(typeof Function); //function
函數對象是function;普通對象是object。下面看經常使用的幾種生成對象的方法:函數
var o1 = {}; var o2 = new Object; var o3 = new Object(); var o4 = new Object(undefined); var o5 = new Object(null); var o6 = Object.create(Object.prototype); var o7 = Object.create(null); console.log(typeof o1); // object console.log(typeof o2); // object console.log(typeof o3); // object console.log(typeof o4); // object console.log(typeof o5); // object console.log(typeof o6); // object console.log(typeof o7); // object function f1(){}; var f2 = function(){}; var f3 = new Function('str','console.log(str)'); console.log(typeof f1);// function console.log(typeof f2);// function console.log(typeof f3);// function var o8 = new f1(); console.log(typeof o8);// object
記住,凡是經過new Function()或function關鍵字建立的對象都是函數對象,其餘是普通對象。Object和Function也都是經過new Function()建立的。this
在js中,每當定義一個對象,對象中都會有一些預約義的屬性。其中函數對象的一個屬性就是原型對象prototype;普通對象沒有prototype,但有__proto__屬性。打印o1-o8發現,除了o7其餘都同樣。spa
o7: Object{No Properties} 其餘: Object{__proto__: Object}
而f1-f3卻都不同。prototype
f1: function f1(){} f2: function (){} // 匿名函數 f3: function anonymous(str/**/) { // anonymous意思是匿名 console.log(str) }
發現打印不出prototype,咱們直接打印prototype試試:code
console.log(typeof f1.prototype);console.log(f1.prototype); 結果以下: object Object{constructor: f1(), __proto__: Object} console.log(typeof f2.prototype);console.log(f2.prototype); 結果以下: object Object{constructor: (),__proto__: Object} console.log(typeof f3.prototype);console.log(f3.prototype); 結果以下: object Object{constructor:anonymous(str/**/),__proto__:Object}
再打印Object.prototype和Functjion.prototype試試htm
console.log(typeof Object.prototype);console.log(Object.prototype); 結果以下: object Object{ __defineGetter__:__defineGetter__() __defineSetter__:__defineSetter__() __lookupGetter__:__lookupGetter__() __lookupSetter__:__lookupSetter__() constructor:Object() hasOwnProperty:hasOwnProperty() isPrototypeOf:isPrototypeOf() propertyIsEnumerable:propertyIsEnumerable() toLocaleString:toLocaleString() toString:toString() valueOf:valueOf() get __proto__:__proto__() set __proto__:__proto__() } console.log(typeof Function.prototype);console.log(Function.prototype); 結果以下: function function () {}
var person = function(name){ this.name = name }; person.prototype.getName = function(){ return this.name; } var zzz = new person('zzz'); console.log(zzz.getName()); // zzz
原型鏈中增長一個函數,他的實例就能夠直接使用這個函數了。對象
js在建立對象的時候都有一個__proto__屬性,指向建立它的函數的prototype屬性。內存
1. console.log(zzz.__proto__ == person.prototype);// true 2. console.log(person.__proto__ == Function.prototype);// true 3. console.log(person.prototype.__proto__ == Object.prototype);// true 4. console.log(Object.__proto__ == Function.prototype);// true 5. console.log(Function.__proto__ == Function.prototype);//true 6. console.log(Function.prototype.__proto__ == Object.prototype);//true
分析1:zzz是person建立的,因此person.__proto__指向person.prototype.
分析2:person是Function建立的,因此person.__proto__指向Function.prototype.
分析3:person.prototype是個對象,是Object建立的。
分析4:Object是Function建立的。
分析5:Function也是本身建立的,比較特殊。
分析6:Function的prototype是對象,Object建立的。
總結:
1. 有prototype都是object,因此全部prototype的__proto__都指向Object的prototype。 2. Object的prototype的__prototype__特殊,指向null. 3. Function的__proto__也比較特殊,指向本身的prototype.
圖解以下:
另外,原型對象prototype中都有一個constructor屬性,用來引用他的函數對象,即。
person.prototype.constructor === person;// true
JS原型與原型鏈終極詳解
附本身理解的原文章中的內存分析圖: