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原型与原型链终极详解
附本身理解的原文章中的内存分析图: