以下是我自己总结的规律,有可能不对。阅读请注意
[sc name="quote-black" ]首先万物皆对象,就算声明一个函数类型,这个函数也本质是个对象。[/sc]
声明体
proto返回声明体的前半截的原型对象。
prototype返回声明体的后半截的原型对象。
例如:
function Foo(){};
这代码声明了一个函数对象Foo
因为前半截声明为function,后半截为Foo
所以:
Foo.proto返回Function.prototype
Foo.prototype返回Foo.prototype(由环境设置的对象)
实例化
如果用new实例化Foo的话
a = new Foo();
a在这里接收到一个对象后,a的类型就变为Foo object了
所以a.proto将返回Foo.prototype
所以a.prototype将返回a.prototype(一般为undefined)
循环引用
a = {};
b = {};
a.prototype=b; // OK
b.prototype=a; // OK
a.__proto__=b; // OK
b.__proto__=a; // Error: Cyclic __proto__ value
查值
a = {};
b = {name:'MiLai'};
a.prototype=b;
console.log(a.name); // undefined
a = {};
b = {name:'MiLai'};
a.__proto__=b;
console.log(a.name); // MiLai
类的实现
function a(){this.data = 3;}; // a.prototype 将自动生成
a.prototype.say = function(){console.log("Hi");};
b = new a();
/*
b = {};
b.__proto__ = a.prototype;
this = b;
b.__proto__.constructor();
*/
b.say(); // Hi
console.log(b.data); // 3
c = new a();
c.say = function(){console.log("Hello")};
c.say(); // Hello
console.log(c.data); // 3
c.data=4;
console.log(c.data); // 4
console.log(b.data); // 3
a.prototype.data = 5;
console.log(c.data); // 4
console.log(b.data); // 3
b.data = undefined;
console.log(c.data); // 4
console.log(b.data); // undefined
console.log(b.hasOwnProperty('data')); // true
delete b.data;
console.log(c.data); // 4
console.log(b.data); // 5
console.log(b.hasOwnProperty('data')); // false
js内部调用Object.prototype.hasOwnProperty(key)来判断是否需要递归原型链
一般来讲,[‘prototype’]只是new这个操作的时候会用到的一个属性,把新对象的[[Prototype]]指向构造函数的[‘prototype’]。函数以外的其他地方一般用不到[‘prototype’]
function b() {}
var a = new b;
// a的__proto__指向了b.prototype