基于原型的语言?
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
注意:原型是每个实例都具有的属性,而prototype是函数的属性,通过prototype属性获得函数的原型
实例1
function doSomething(){}
doSomething.prototype.foo = "bar";//可以添加一些属性到 doSomething 的原型上面
console.log( doSomething.prototype );
然后,我们可以使用 new 运算符来在现在的这个原型基础之上,创建一个 doSomething 的实例。正确使用 new 运算符的方法就是在正常调用函数时,在函数名的前面加上一个 new 前缀. 通过这种方法,在调用函数前加一个 new ,它就会返回一个这个函数的实例化对象. 然后,就可以在这个对象上面添加一些属性. 看.
实例2
function doSomething(){}
doSomething.prototype.foo = "bar"; // add a property onto the prototype
var doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value"; // add a property onto the object
console.log( doSomeInstancing );
结果:
{
prop: "some value",
__proto__: {
foo: "bar",
constructor: ƒ doSomething(),
__proto__: {
constructor: ƒ Object(),
hasOwnProperty: ƒ hasOwnProperty(),
isPrototypeOf: ƒ isPrototypeOf(),
propertyIsEnumerable: ƒ propertyIsEnumerable(),
toLocaleString: ƒ toLocaleString(),
toString: ƒ toString(),
valueOf: ƒ valueOf()
}
}
}
解析:
doSomeInstancing 的 proto 属性就是doSomething.prototype. 但是这又有什么用呢? 好吧,当你访问 doSomeInstancing 的一个属性, 浏览器首先查找 doSomeInstancing 是否有这个属性. 如果 doSomeInstancing 没有这个属性, 然后浏览器就会在 doSomeInstancing 的 proto 中查找这个属性(也就是 doSomething.prototype). 如果 doSomeInstancing 的 proto 有这个属性, 那么 doSomeInstancing 的 proto 上的这个属性就会被使用. 否则, 如果 doSomeInstancing 的 proto 没有这个属性, 浏览器就会去查找 doSomeInstancing 的 proto 的 proto ,看它是否有这个属性. 默认情况下, 所有函数的原型属性的 proto 就是 window.Object.prototype. 所以 doSomeInstancing 的 proto 的 proto (也就是 doSomething.prototype 的 proto (也就是 Object.prototype)) 会被查找是否有这个属性. 如果没有在它里面找到这个属性, 然后就会在 doSomeInstancing 的 proto 的 proto 的 proto 里面查找. 然而这有一个问题: doSomeInstancing 的 proto 的 proto 的 proto 不存在. 最后, 原型链上面的所有的 proto 都被找完了, 浏览器所有已经声明了的 proto 上都不存在这个属性,然后就得出结论,这个属性是 undefined.