假设我们创建一个名为' Shape'的函数,并添加一个属性' name' &安培;方法' toString'在它的原型上:
var Shape = function () {};
Shape.prototype.name = 'Shape';
Shape.prototype.toString = function () {
return this.name;
}
console.log(Shape.name); // ''
console.log(Shape.toString()); // function () {}
var Triangle = new Shape();
console.log(Triangle.name); // 'Shape'
console.log(Triangle.toString()); // 'Shape'
' NEW'运营商做了两件事: 它将此指向“三角形”。 它将Triangle的[[proto]]指向Shape.prototype
然后我可以理解当我打电话给姓名&在Triangle上的toString,它搜索它的原型链直到Shape.prototype。
但我的问题是为什么Shape不能搜索它的属性(即使它是一个对象)的方法&属性?
感谢。
答案 0 :(得分:3)
当您访问对象上的属性时,Javascript会直接在对象上查找已直接添加到对象的任何属性(这些属性称为"拥有"属性)。如果它没有在那里找到属性,那么它会查找原型链。
所以,当你这样做时:
var Triangle = new Shape();
console.log(Triangle.toString()); // 'Shape'
它在名为Triangle的实际对象上查找.toString()
属性,但该对象上没有该名称的属性。因此,由于它没有直接在对象上找到任何内容,因此它会查看原型并在那里找到Shape.prototype.toString()
实现,这就是执行的内容。
原型的引用在创建时存储在Triangle对象上。它不存储在.prototype
属性中 - 该属性仅用于构造函数。相反,每个JS版本都有自己的方式来存储对原型的引用,并且它对于所有浏览器传统上并不相同,并且它的存储方式是非标准的。它最初仅供JS引擎内部使用。例如,Chrome会将其存储在名为obj.__proto__
的属性中,但IE不会。为了解决这种标准化的缺失,有一种名为obj.getPrototypeOf()
的新方法,现在可以在现代浏览器中使用它来访问给定对象的原型。在任何情况下,JS引擎在解析在实际对象本身上找不到的属性名时会自动搜索这个原型。
如果你这样做了:
var Triangle = new Shape();
Triangle.toString = function() {
return 'Shape named Triangle';
}
console.log(Triangle.toString()); // 'Shape named Triangle'
然后,javascript将首先找到您直接附加到对象的toString()
实现,它将执行该实现而不是原型上的实现。
答案 1 :(得分:1)
所以我根据我所知道的添加。
此处Shape
是一个功能&函数只是一种特殊的对象,就像函数可以拥有属性的任何对象一样。
函数自动获取名为prototype
的属性,该属性只是一个空对象。这个对象得到了一些特殊的处理。
当您执行new
Function
时,创建的对象会继承其构造函数原型的所有属性。
喜欢吼叫
var Shape = function () {};
Shape.prototype.name = 'Shape';
Shape.prototype.toString = function () {
return this.name;
}
当你说
时var Triangle = new Shape();
那它做什么
var Triangle = {};
Triangle.name = Shape.prototype.name
Triangle.toString = Shape.prototype.toString;
“它将对象Triangle
设置为委托给Shape.prototype。”
所以当你做的时候
Triangle.name //Shape
Triangle.toString() // Shape
但对Shape
你必须说
Shape.prototype.name //Shape
Shape.prototype.toString() //Shape
答案 2 :(得分:0)
因为Triangle
是object
,其中Shape
是一个函数(一种对象),所以当你请求一个函数的属性而它找不到它时,不会搜索它的prototype
属性。但您可以修改Function.prototype.name/toSTring()