【问题标题】:What is the idea behind get and set in javascript?javascript中get和set背后的想法是什么?
【发布时间】:2017-12-20 19:55:34
【问题描述】:

大家好,我目前正在学习如何在 javascript 中获取和设置炒锅。具体说说对象atm。

let person = {
  _name: 'Lu Xun',
  _age: 137,
  
  set age(ageIn) {
    if (typeof ageIn === 'number') {
      this._age = ageIn;
    }
    else {
      console.log('Invalid input');
      return 'Invalid input';
    }
  },
  
  get age() {
    console.log(`${this._name} is ${this._age} years old.`);
    return this._age;
  }

};


person.age = 'Thirty-nine';
person.age = 39;

console.log(person.age);

例如在此代码中。为什么我需要 set 或 get ,为什么我不能像这样访问它:person.age = 59; ?意思是为什么我不能直接通过我的代码示例更改它?我无法掌握这个概念和对它的需求?有人可以彻底向我解释吗?有人可以给我一个易于理解的解释示例吗?

【问题讨论】:

  • 对于初学者,它允许您处理验证等事情,就像您在此处所做的那样
  • 公平地说,您的场景根本不需要 getter 或 setter。但这并不妨碍您使用它。如果不是年龄,而且打字更糟糕怎么办?
  • 这只是一个允许this concept的漂亮方式
  • 属性可用于所有高级 oo 编程语言。我想到的一种用法是只读属性和计算属性。
  • 我仍然不明白如何以及何时使用它们

标签: javascript object get set


【解决方案1】:

对象具有属性和方法。属性是描述对象所处状态的一种方式,方法是改变该状态并让对象“表现”的方式:

 class Person {
   constructor(name){
      this.name = name; //name is a property
   }
   //And here weve got a method:
   sayHi(){
      alert(`Hi, im ${this.name}!`);
   }
 }

然而,在大多数情况下,将“状态”和“行为”(也称为属性和方法)分开是非常清楚的,但有时却不是。让我们想象一下这个人有一个标签签名方法:

 showLabel(){
   document.body.innerHTML = this.name;
 }

现在我们更改人名,例如:

 const person = new Person("Jake");
 person.showLabel();
 person.name = "Jack";

但是,标签不会更新 :/,所以当我们将 Jake 重命名为 Jack 时,他的标签仍然显示 Jake。那很糟。为此,发明了 getter 和 setter。这些方法的主要目的是获取和设置属性(惊喜;)),但它们也可以防止像上述那样的故障,并且它们有很多优点,这就是they are used excessively in other languages 的原因。 Person 的示例设置器是:

 setName(name){
   //Set
   this.name = name;
   //Prevent glitches
   this.showLabel();
 }

因此,我们现在将设置器称为person.setName("Jack"),而不是直接设置person.name。然而,现在我们在属性和 不应该设置的属性之间出现了不一致,而应该使用 setter 来代替。为了解决这种不一致,js 引入了getset。在内部它表现得像方法,在外部它仍然看起来像一个简单的属性:

 get name(){ return this._name }
 set name(value){
  this._name = value;
  this.showLabel();
 }

可用作:

 const person = new Person("Jake");
 person.showLabel();
 person.name = "Jack"; //let the magic happen ;)

TLDR:getset 基本上是属性和方法的混合,以结合两者的优点并保持一致性。

【讨论】:

  • 次要观点:从技术上讲,JavaScript 对象没有方法——它们只有属性。一些属性存储简单的原始数据,而其他属性存储函数。当您调用我们通常所说的方法时,您真正做的是访问存储在属性中的函数(作为数据),然后通过将() 附加到您刚刚查找的内容来调用它。这就是为什么我们可以引用存储在属性中的函数而不调用它们。
  • 那么我做对了吗? Getter 和 setter 用于操作 ex 键中的属性。 name: oli; ?是不是他们是私人的?并且不能在对象之外进行更改,因此您必须定义一个 set 或 get 函数来更改它您可以在对象之外访问哪个?
  • 我在这方面真的很挣扎
  • @itsolidude 实际上 js 没有真正的私有属性(还没有!)。所以它的约定是用_ 标记内部属性,我在上面做了。因此,使用 getter/setter (name) 公开的属性(如果您在方法中执行 this.name = "whatever" 也会调用它)和保持属性状态的内部属性 (this._name) 很常见跨度>
  • @itsolidude 我认为你在这方面做得太多了,而且使问题复杂化了。有时需要检查用户想要为属性设置的值的有效性,这就是 setter 可以为您做的事情,有时需要在将值返回给您之前对其进行操作,这就是 getter 所做的事情。
【解决方案2】:

getset 属性被称为 "Accessor Properties" and they differ from "Data properties"(即obj.prop = value),因为它们允许在 get 和 set 操作期间实现逻辑,这非常适合验证和操作。

如果您有一个带有age 属性的Person 对象,这有意义吗?

Person.age = "green";

当然不会,但是常规的“数据”属性会允许这样做。但是,使用set“访问器”属性,我们可以禁止超出范围的非数字和数字数据。

var Person = {
   _age:0,
   // Accessor Property:
   get age() {
     return _age;
   },
   set age(value) {
     // Can't be non-numeric or out of range
     if (/^\d+$/.test(value) && value > 0 && value < 110) {
       this._age = value;
     }
   }
};

但是,它们在处理继承属性时 set 操作的处理方式也有所不同。

这是一个例子:

var Product = {
   // Data Properties:
   sku: 12345,
   name: "Super Widget",
   mfg: "ACME Corp.",
   retail: 9.95,
   suggestedWholesale: 14.95,
   implementationDate: new Date(2012, 06, 04).toLocaleDateString(),
   // Accessor Property:
   get markup() {
     // Return the difference between wholesale and retail price
     return (this.suggestedWholesale - this.retail).toFixed(2);
   },
   set markup(value) {
     // Markup cannot be more than 100
     if (value <= 100) {
       this.suggestedWholesale = this.retail + value;
     }
   }
};

// Make a new object that inherits from Product
var newProduct = Object.create(Product);

// When you GET a property value, the entire prototype chain is
// checked until the property is found or else you'll get undefined.
console.log(newProduct.name);
console.log(newProduct.markup);

// When you SET a property value, the property is ALWAYS used
// on the CURRENT object as an "own".  If the property being
// set matches an inherited property of the same name, the new
// "own" property hides the inherited one.
newProduct.name = "FOO";
console.log(newProduct.name);  // Successful override of inherited property
console.log(Product.name);     // Original object still has original property value

// EXCEPTION: accessor properties - With these the prototype chain is used:
newProduct.markup = 101; // Not allowed according to inherited set logic
console.log(newProduct.markup);  // Value doesn't change because inherited accessor set is used!

【讨论】:

    猜你喜欢
    • 2015-01-22
    • 2014-06-09
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多