原型继承是否根据类型表现不同?在这两种情况下,上下文引用THIS是否有所不同?为什么在这个例子中,一个是访问原型而另一个是为对象创建一个新属性?
var Player = function(){};
Player.prototype.name = '';
Player.prototype.set_name = function(name){this.name = name;}
var p1 = new Player();
var p2 = new Player();
p1.set_name('Johanna');
这两个值的回报:
// Checking object properties
>p1
Player {name: "Johanna", set_name: function}
>p2
Player {name: "", set_name: function}
// Checking prototypes
>p1.__proto__
Object {name: "", set_name: function}
>p2.__proto__
Object {name: "", set_name: function}
但是,如果我使用名称作为对象属性执行播放器,则函数set_name正在修改原型。
var Player = function(){};
Player.prototype.name = {};
Player.prototype.set_name = function(name){this.name['first_name'] = name;}
var p1 = new Player();
var p2 = new Player();
p1.set_name('Andrew');
这两个值的回报:
// Checking object properties
>p1.name
Object {first_name: "Andrew"}
>p2.name
Object {first_name: "Andrew"}
// Checking prototypes
>p1.__proto__.name
Object {first_name: "Andrew"}
>p2.__proto__.name
Object {first_name: "Andrew"}
为什么会这样?我错过了哪些概念?
答案 0 :(得分:2)
继承链
使用构造函数创建对象时,继承链如下所示,用于查找。
将搜索当前对象。
将搜索父母的原型。
将搜索父母的父母的原型。
...
最后将搜索全局对象。如果在任何地方都找不到,则会返回undefined
。如果在任何这些级别中找到要查找的值,它将立即返回。
注意:分配不会上传继承链。如果为对象的属性赋值(如果它不存在则会创建),则该值将分配给该属性。
第一种情况:
你在做什么
this.name = name;
所以,
p1.set_name('Andrew');
在name
中创建新的p1
属性,并在其中存储Andrew
。当您尝试打印p1
时,会在p1
上查找该名称,并在p1
本身找到该名称。所以,Andrew
被退回了。但是,当您打印p2
时,p2
中找不到姓名。它在层次结构中上升并在父级原型中找到name
。所以,它返回空字符串。
第二种情况:
你在做什么
this.name['first_name'] = name;
所以,
p1.set_name('Andrew');
在name
中查找p1
。因为您尝试访问'first_name'
上的this.name
。因此,它尝试检索name
属性。它在p1
中找不到它,所以在父母的原型中找到它。它是一个空对象,name
被分配给该对象的first_name
属性。
我们知道p2
的原型与p1
的原型相同。我们可以像这样确认
console.log(p1.__proto__ === p2.__proto__);
# true
因此,当您查找与p2
原型相同的p1
原型时,会找到名称Andrew
。
答案 1 :(得分:0)
作为一般情况,变量等在构造函数中设置。 有关该主题的更多信息以及比我在此处可以参考的更好的解释:http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/
// Constructor
function Player() {
this.names = '';
};
// Public Method
Player.prototype.set_name = function(name){
this.name = name;
}
// Static method
Player.walk = function() {}
var player1 = new Player();
player1.set_name('John Doe'); // fires the public method
Player.walk(); // fires the static method