【问题标题】:JavaScript properties with setter methods aren't real properties?带有 setter 方法的 JavaScript 属性不是真正的属性吗?
【发布时间】:2014-12-28 02:50:09
【问题描述】:
function Name(first, last) {
  this.first = first;
  this.last = last;
  this.fullName = first + " " + last
}

Name.prototype = {
  get fullName() {
    return this.first + " " + this.last;
  },

  set fullName(name) {
    var names = name.split(" ");
    this.first = names[0];
    this.last = names[1];
  }
};

var person = new Name("Foo", "Bar");
// person.fullName = "Foo Bar"
person.hasOwnProperty("fullName") // false

有没有办法返回属性?

【问题讨论】:

  • 那么,您只是在问为什么.hasOwnProperty() 在您的情况下返回false?如果是这样,那么也许你真的应该问这个。

标签: javascript inheritance


【解决方案1】:

hasOwnProperty 不会检查对象的原型链,在您的情况下,人 getset 是通过原型链继承的

hasOwnProperty

从 Object 派生的每个对象都继承了 hasOwnProperty 方法。 这个方法可以用来判断一个对象是否有 指明财产作为该物件的直接财产;不像在 运算符,此方法不检查对象的原型 链。

function Name(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = first + " " + last;
}
var person = new Name("Foo", "Bar");
console.log(person.fullName);
console.log(person.hasOwnProperty("fullName")); // true
console.log(Name.prototype.hasOwnProperty("fullName")); // false

for (var prop in person) {
    console.log(prop);
}

console.log('');

Name.prototype = {
    get fullName() {
        return this.first + " " + this.last;
    },

    set fullName(name) {
        var names = name.split(" ");
        this.first = names[0];
        this.last = names[1];
    }
};
var person2 = new Name("Foo", "Bar");
console.log(person2.fullName);
console.log(person2.hasOwnProperty("fullName")); // false
console.log(Name.prototype.hasOwnProperty("fullName")); // true

引用@JLRishe

当你使用 this.fullName = "...";在你的构造函数中,你是 调用继承的 setter,而不是添加新属性。

如果你想找到这样的属性,你可以使用 for... in 语句:

for (var prop in person) {
    console.log(prop);
}

【讨论】:

  • 由于你的答案是最受好评的答案,我建议在此处解释为什么 this.fullName = first + " " + last 没有为新对象提供自己的 fullName 属性。
【解决方案2】:

正如 InvernoMuto 指出的,Object.hasOwnProperty("fullName") 返回false,因为它不是person 自己的财产;它是通过原型链继承的。当您在构造函数中使用 this.fullName = "..."; 时,您调用的是继承的 setter,而不是添加新属性。

如果你想找到这样的属性,你可以:

  1. 使用for..in 循环:
for (var prop in person) {
    // this will iterate over EVERY property in person's prototype chain
}
  1. 在构造函数中附加属性:

function Name(first, last) {
  this.first = first;
  this.last = last;

  Object.defineProperty(this, "fullName", {
    get: function() {
      return this.first + " " + this.last;
    },
    set: function(name) {
      var names = name.split(" ");
      this.first = names[0];
      this.last = names[1];
    }
  });
}

var person = new Name("Ronald", "McDonald");
console.log(person.hasOwnProperty("fullName")); // true
  1. 在构造函数中创建一个全新的对象,使用那里的get/set 语法。在这种情况下,我们不会使用 new 关键字,而只是调用函数:

function Name(first, last) {
    return {
        first: first,
        last: last, 

        get fullName() { return this.first + " " + this.last; },
        set fullName(name) { 
            var names = name.split(" ");
            this.first = names[0];
            this.last = names[1];
        }
    };
};

var person = Name("Ronald", "McDonald");
console.log(person.hasOwnProperty("fullName")); // true

【讨论】:

    【解决方案3】:

    根据MDN,“get 语法将对象属性绑定到在查找该属性时将调用的函数。”这意味着每当您尝试访问Name 实例的fullName(例如person.fullName)时,javascript 将委托给该getter 函数,该函数恰好位于Name.prototype 对象上。

    此外,“set 语法将对象属性绑定到要在尝试设置该属性时调用的函数。”因此,即使显式地为每个实例提供 fullName 属性,javascript 实际上也会查看原型上的 set 函数。如果你想解决这个问题,并让person.hasOwnProperty("fullName") 返回 true,你可以这样做:

    function Name(first, last) {
      this.first = first;
      this.last = last;
      this.fullName = first + " " + last
    }
    
    Name.prototype.setFullName = function(fullName){
      var names = fullName.split(" ");
      this.first = names[0];
      this.last = names[1];
      this.fullName = fullName;
    };
    
    var person = new Name("Foo", "Bar");
    // person.fullName = "Foo Bar"
    person.hasOwnProperty("fullName") // true
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 2011-10-17
      • 1970-01-01
      • 2022-10-05
      相关资源
      最近更新 更多