【问题标题】:Javascript use of Object.create and properties pointers not being dereferenced from prototypeJavascript 使用 Object.create 和未从原型取消引用的属性指针
【发布时间】:2015-11-02 16:25:51
【问题描述】:

当我o1.set('bar'); 时,谁能解释下面发生了什么?我想知道为什么此时还设置了o2.name,而当我o2.set('fox');,我的意思是o1.name 仍然是bar 时,同样的情况不会发生。

为什么 o1.name 和 o2.name 指向同一个对象,即使我更改了旧值 (foo) 但更改 o2.name 时却没有发生同样的情况?

var Person = {
	name: "foo",
	get: function get() {
		return this.name;
	},
	set: function set(sur) {
		this.name = sur;
	}
},
o1 = Person,
o2 = Object.create(o1);

// true "foo" "foo"
console.log(o1.name === o2.name, o1.get(), o2.get()); 

o1.set('bar');

// true "bar" "bar"
console.log(o1.name === o2.name, o1.get(), o2.get());

o2.set('fox');

// false "bar" "fox"
console.log(o1.name === o2.name, o1.get(), o2.get());

下面可以看到另一种行为。这里的不同之处在于,我甚至为 o1 对象扩展了 Person 原型。

	var Person = {
		name: "foo",
		get: function get() {
			return this.name;
		},
		set: function set(sur) {
			this.name = sur;
		}
	},
	o1 = Object.create(Person),
	o2 = Object.create(Person);

	// true "foo" "foo"
	console.log(o1.name === o2.name, o1.get(), o2.get()); 

	o1.set('bar');

	// false "bar" "foo"
	console.log(o1.name === o2.name, o1.get(), o2.get());

	o2.set('fox');

	// false "bar" "fox"
	console.log(o1.name === o2.name, o1.get(), o2.get());

【问题讨论】:

    标签: javascript object prototype prototypal-inheritance


    【解决方案1】:

    对象o2继承其原型链中的“名称”属性。但是,一旦设置了属性,受影响的就是对象本身。

    换句话说,在设置对象属性时不参考原型链。更新(或添加)的属性始终直接在目标对象上。只有在检查属性值时才会参考原型链。

    在调用o2.set("fox"); 中,set() 函数本身就在原型中。但是,该调用中this 的值是o2,而不是o1,因此对this.name 的赋值会直接影响o2

    【讨论】:

    • 非常好@Pointy,您能否添加一些有关该主题的链接,以便深入解释?
    • @thiagoh 我不知道此行为的任何具体参考;这就是语言的工作原理。
    【解决方案2】:

    可以在 Eric Elliot 所著的“Programming JavaScript Applications”一书中找到答案,我认为可以在Delegate Prototypes 找到这个问题。

    埃里克说:

    "在 JavaScript 中,对象具有对委托原型的内部引用。当查询对象的属性或方法时,JavaScript 引擎首先检查该对象。如果该对象上不存在该键,它检查委托原型,依此类推原型链。原型链通常以 Object 原型结束。"

    并用以下内容完成解释:

    原型上的属性就像默认值一样。当你在实例上设置它们时,实例值会覆盖该实例的值。

    换句话说,我知道当调用o1.get() 时我正在更改原型,而o2 对象正在扩展它。但是,当我调用o2.get() 时,我不再更改原型,而是更改o2 实例。这就是为什么在那之后o1.name 上的任何更改现在都与o2.name 分离。

    【讨论】:

      猜你喜欢
      • 2012-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-01
      • 1970-01-01
      • 2016-07-10
      • 2016-04-18
      相关资源
      最近更新 更多