var plainObject = {}; // plainObject是一个最普通的对象了
console.log(plainObject.__proto__); // __proto__ 属性是这个对象的原型的引用, 会打印: {} , {} 就是 Object 就是每个对象的默认的原型
var aPrototype = {
show: function() {
console.log("hello world!");
}
};
plainObject.__proto__ = aPrototype; // 手动把 plainObject的__proto__改成了 aPrototype 对象,而不是 Object
//由于 plainObject的原型,也就是 aPrototype对象内有show 函数,这样 plainObject 也就有了 show 函数
plainObject.show(); //所以这里调用show函数是不会出错的
//如果要批量的创建很多对象,这些对象的原型都是一样的,用上面的方式就得
var o = {};
o.__proto__ = aPrototype;
var o1 = {};
o1.__proto__ = aPrototype;
var o2 = {};
o2.__proto__ = aPrototype;
//一次类推,代码不好看,所以JavaScript通过构造函数来指定prototype
var MyClass = function() { //这是一个函数,所以就是一个构造函数,JavaScript里的每一个函数都可以当成构造函数用
};
MyClass.prototype = aPrototype; //设置构造函数的prototype属性,指向 aPrototype
var o3 = new MyClass(); //用MyClass构建一个对象,JavaScript会自动的把 o3.__proto__ 设置成 MyClass.prototype,因为MyClass是o3的构造函数
o3.show(); //这样 o3就有他原型的 show 函数可以用了。
var o4 = new MyClass();
var o5 = new MyClass();
//这样创建起来就比之前要简洁了
//由这个构造函数构建的对象,也都有 show 函数
var AnotherClass = function() {
this.show = function() {//设置被构造对象的show属性为这个匿名函数
console.log("I am a property of an instance!");
}
}
var o6 = new AnotherClass();
o6.show(); // o6的原型是 Object,没有 show 函数,但是构造函数 AnotherClass给o6设置了show属性为函数,所以也可以调用
var o7 = new AnotherClass();
//那么既然如此,还要原型做什么?
// 1 原型更节省内存 , 因为相同原型的对象共享原型的函数,比如上面的 o.show o1.show o2.show 这个变量实际上都指向 aPrototype.show,是同一个函数
// 只占用一个函数的内存。但是 o6.show 和 o7.show 就是两个函数,这两个函数是在 AnotherClass函数内分贝创建的,会占用两个函数的内存空间。
// 2 改变原型会改变所有用这个对象作为原型的对象,无论是什么时候被创建的。但是改变构造函数,只会对之后新构造的对象有用,比如
aPrototype.show = function() { //改变了 aPrototype的show函数
console.log("new show in prototype");
};
plainObject.show(); // 会输出 new show in prototype
// 3 原型可以形成链
var bPrototype = { //再建一个对象当原型用
say : function() {
console.log("I am say!")
}
}
aPrototype.__proto__ = bPrototype; // aPrototype的原型是 bPrototype
plainObject.say(); //会输出 I am say! ,因为 plainObject.__proto__.__proto__,也就是bProotype,有一个函数say
//plainObject的原型是 aPrototype, aPrototype的原型是 bPrototype
//bPrototype是 plainObject的原型的原型
//因为Object是 bPrototype的原型,所以plainObject的原型的原型的原型就是 Object 构造函数的 prototype
if (plainObject.__proto__.__proto__.__proto__ == Object.prototype) {
console.log("true") //这里会输出 true
}