我指的是Helephant.com上一篇文章的网络档案,以了解Javascript在对对象调用时如何解析原型链中的函数。
文章引用
如果对象上没有直接设置方法,javascript就会查找创建该对象的Constructor函数。Javascript检查该方法的构造函数原型属性。
在下面的代码中,如果您检查rufus.constructor
是全局Object()
构造函数,那么JS将直接检查全局Object((,因为rufus.constructor
是Object()
,或者根据上面的文章引用,它将首先查看构造函数,然后找到原型属性,依此类推。JS将如何解析函数(rufus.toString
(。我对此很困惑。
//PET CONSTRUCTOR
function Pet(name, species, hello)
{ this.name = name;
this.species = species;
this.hello = hello; }
Pet.prototype = {
sayHello : function(){
alert(this.hello);
}
}
//CAT CONSTRUCTOR
function Cat(name, hello, breed, whiskerLength)
{ this.name = name;
this.hello = hello;
this.breed = breed;
this.whiskerLength = whiskerLength;}
Cat.prototype = new Pet();
var rufus = new Cat("rufus", "miaow", "Maine Coon", 7);
rufus.toString;
如果对象上没有直接设置方法,则javascript然后查找创建该对象的Constructor函数。Javascript检查该方法的构造函数原型属性。
措辞令人困惑。JavaScript通过__proto__
查找原型链,并且不使用constructor
属性。他们提到Constructor
是因为通常情况下,对象就是通过Constructor.prototype
属性获得原型的。但事实并非总是如此。你可以这样设置原型:
var rufus2 = Object.create(new Pet());
Object.getPrototypeOf(rufus) === Object.getPrototypeOf(rufus2); // true
关于如何解决toString
方法:
rufus.hasOwnProperty('toString'); // false -> go up
(new Pet()) rufus.__proto__.hasOwnProperty('toString'); // false -> go up
({sayHello :...}) rufus.__proto__.__proto__.hasOwnProperty('toString'); // false -> go up
(Object.prototype) rufus.__proto__.__proto__.__proto__.hasOwnProperty('toString'); // true
function Person () { }
Person.prototype.sayName = function () { };
var bob = new Person();
console.log(bob.sayName === Person.prototype.sayName); // true
console.log(bob.constructor.prototype.sayName === Person.prototype.sayName); // true
console.log(bob.__proto__.sayName === Person.prototype.sayName); // true
console.log(bob.constructor === Person); // true
console.log(bob.__proto__ === Person.prototype); // true
这就是你们的关系
如果在对象上找不到属性/函数,则它会沿着__proto__
链向上查找它要查找的内容。在较旧的浏览器中,__proto__
对JS开发人员不可访问,但仍然是浏览器/节点在后台使用的对象,以引用Constructor.prototype属性。
PS:尽量不要在JS中使用深层结构。这是一条充满泪水的道路。在其他基于类的语言中,深层次的层次结构会带来痛苦,但在JS中则是痛苦的,在JS中,通常一个函数就足够了。