带有 setter 方法的 JavaScript 属性不是真正的属性

JavaScript properties with setter methods aren't real properties?

本文关键字:属性 JavaScript setter 方法 带有      更新时间:2023-09-26
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 不会检查对象的原型链,在您的情况下,人getset都是通过原型链继承

拥有自己的财产

从 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...在声明中:

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

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

根据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