在TypeScript中获取和设置

Mur*_*nze 568 typescript

我正在尝试为属性创建get和set方法:

private _name: string;

Name() {
    get:
    {
        return this._name;
    }
    set:
    {
        this._name = ???;
    }
}
Run Code Online (Sandbox Code Playgroud)

设置值的关键字是什么?

Ezw*_*ard 942

Typescript使用与ActionScript3类似的getter/setter语法.

class foo {
    private _bar: boolean = false;
    get bar(): boolean {
        return this._bar;
    }
    set bar(value: boolean) {
        this._bar = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将使用Ecmascript 5 Object.defineProperty()功能生成此Javascript.

var foo = (function () {
    function foo() {
        this._bar = false;
    }
    Object.defineProperty(foo.prototype, "bar", {
        get: function () {
            return this._bar;
        },
        set: function (value) {
            this._bar = value;
        },
        enumerable: true,
        configurable: true
    });
    return foo;
})();
Run Code Online (Sandbox Code Playgroud)

所以要使用它,

var myFoo = new foo();
if(myFoo.bar) {         // calls the getter
    myFoo.bar = false;  // calls the setter and passes false
}
Run Code Online (Sandbox Code Playgroud)

但是,为了完全使用它,您必须确保TypeScript编译器以ECMAScript5为目标.如果您正在运行命令行编译器,请使用--target标志,如下所示;

tsc - 目标ES5

如果使用的是Visual Studio,则必须编辑项目文件,以将标志添加到TypeScriptCompile构建工具的配置中.你可以在这里看到:

正如@DanFromGermany在下面所建议的那样,如果你只是在阅读和编写像foo.bar = true这样的本地属性,那么拥有一个setter和getter对就是矫枉过正.如果您需要在读取或写入属性时执行某些操作(如日志记录),则可以随后添加它们.

  • 很好的答案.另请注意,与C#不同,TypeScript中当前未对属性进行虚拟化(v0.9.5).在派生类中实现"get bar()"时,您将替换父级中的"get bar()".含义包括无法从派生的访问器调用基类访问器.这仅适用于属性 - 方法的行为与您预期的一样.请参阅SteveFenton的回答:http://stackoverflow.com/questions/13121431/typescript-accessing-member-of-base-class (54认同)
  • 关于下划线,我有点困惑.Typescript约定说不要对私有变量使用下划线?但在这种情况下,我们必须使用下划线 - 否则我们将在私人和公共"酒吧"之间发生冲突 (13认同)
  • @DanFromGermany属性是一对"get"和"set"方法的"语法糖".Microsoft使用Visual Basic创建了一个属性概念,并将其转换为.NET语言,如C#和VB.NET.例如,请参见[属性(C#编程指南)](https://docs.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/classes-and-structs/properties).属性简化了对对象状态的访问,并且(在我看来)消除了必须处理"获取/设置"方法对的"嘈杂".(或者有时只需要"获取"需要不变性的方法.) (5认同)
  • 使用下划线是私人财产的个人偏好.但是,我相信你是对的,因为我们希望该属性具有与getter/setter方法不同的名称. (3认同)
  • 为什么使用`myFoo.bar = true`而不是`myFoo.bar(true);`或`myFoo.setBar(true);`?? (3认同)
  • 请注意,在此示例中,您应该只让属性公开。在诸如 Java 之类的语言中,您不想这样做,因为您希望保留稍后在 getter/setter 中添加逻辑的权利,如果有人使用 foo.x = 1 而不是 foo.getX() 你就搞砸了。但是这里 getter 和 setter 的语法与访问公共属性的语法相同,因此您可以随时添加逻辑而不会破坏更改。 (2认同)

Tor*_*Ali 91

Ezward已经提供了一个很好的答案,但我注意到其中一条评论询问它是如何使用的.对于像我这样偶然发现这个问题的人,我认为在Typescript网站上找到关于getter和setter的官方文档的链接是有用的,因为它解释得很好,希望随时更新是最新的制作,并显示示例用法:

http://www.typescriptlang.org/docs/handbook/classes.html

特别是对于那些不熟悉它的人,请注意你没有将"get"这个词加入到对getter的调用中(对于setter来说也是如此):

var myBar = myFoo.getBar(); // wrong    
var myBar = myFoo.get('bar');  // wrong
Run Code Online (Sandbox Code Playgroud)

你应该这样做:

var myBar = myFoo.bar;  // correct (get)
myFoo.bar = true;  // correct (set) (false is correct too obviously!)
Run Code Online (Sandbox Code Playgroud)

给出一个类:

class foo {
  private _bar:boolean = false;

  get bar():boolean {
    return this._bar;
  }
  set bar(theBar:boolean) {
    this._bar = theBar;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后将调用私人'_bar'属性的'bar'getter.

  • 我想知道是否有使用下划线来区分属性名称和 getter 或 setter 方法的解决方法。在我做的一门课程中,他们说下划线不是首选,但没有给出替代方案。 (2认同)
  • @cham你不必在这里使用下划线...如果你愿意,你可以调用私有变量notbar。 (2认同)

小智 52

这是一个可以指向正确方向的工作示例:

class Foo {
    _name;

    get Name() {
        return this._name;
    }

    set Name(val) {
        this._name = val;
    }
}
Run Code Online (Sandbox Code Playgroud)

JavaScript中的getter和setter只是普通函数.setter是一个函数,它接受一个参数,其值是设置的值.

  • 要清楚,不需要属性,getter和setter是"静态的". (29认同)

小智 5

你可以写这个

class Human {
    private firstName : string;
    private lastName : string;

    constructor (
        public FirstName?:string, 
        public LastName?:string) {

    }

    get FirstName() : string {
        console.log("Get FirstName : ", this.firstName);
        return this.firstName;
    }
    set FirstName(value : string) {
        console.log("Set FirstName : ", value);
        this.firstName = value;
    } 

    get LastName() : string {
        console.log("Get LastName : ", this.lastName);
        return this.lastName;
    }
    set LastName(value : string) {
        console.log("Set LastName : ", value);
        this.lastName = value;
    } 

}
Run Code Online (Sandbox Code Playgroud)

  • 是的,此代码中的构造函数不能公开。“ public”在这里定义了重复的成员。 (15认同)
  • 你可以写它,但它不会编译 (4认同)
  • 为什么在构造函数中公开? (2认同)

das*_*dsa 5

我想我可能明白为什么它如此令人困惑。在您的示例中,我们需要 的 getter 和 setter _name。但我们通过为不相关的类变量创建 getter 和 setter 来实现这一点Name

考虑一下:

class Car {
    private tiresCount = 4;
    get yourCarTiresCount(){
        return this.tiresCount;
    }
    set yourCarTiresCount(count) {
        alert('You shouldn\'t change car tire count')
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码执行以下操作:

  1. get并为(而不是set)创建 getter 和 setter 。yourCarTiresCounttiresCount

吸气剂是:

function () {
    return this.tiresCount;
}
Run Code Online (Sandbox Code Playgroud)

设置者是:

function (count) {
    alert('You shouldn\'t change car tire count');
}
Run Code Online (Sandbox Code Playgroud)

意思是,每次我们这样做时new Car().yourCarTiresCount,getter都会运行。对于每个new Car().yourCarTiresCount('7')二传手来说。

  1. 为 private间接创建 getter,但不创建 setter tireCount


Wil*_*een 5

TS 提供了 getter 和 setter,它们允许对象属性更好地控制它们在对象外部的访问(getter)或更新(setter)方式。调用代理函数而不是直接访问或更新属性。

例子:

class Person {
    constructor(name: string) {
        this._name = name;
    }

    private _name: string;

    get name() {
        return this._name;
    }

    // first checks the length of the name and then updates the name.
    set name(name: string) {
        if (name.length > 10) {
            throw new Error("Name has a max length of 10");
        }

        this._name = name;  
    }

    doStuff () {
        this._name = 'foofooooooofoooo';
    }


}

const person = new Person('Willem');

// doesn't throw error, setter function not called within the object method when this._name is changed
person.doStuff();  

// throws error because setter is called and name is longer than 10 characters
person.name = 'barbarbarbarbarbar';  
Run Code Online (Sandbox Code Playgroud)


Yil*_*maz 5

根据您展示的示例,您希望传递一个数据对象并通过 get() 获取该对象的属性。为此,您需要使用泛型类型,因为数据对象是泛型的,可以是任何对象。

export class Attributes<T> {
    constructor(private data: T) {}
    get = <K extends keyof T>(key: K): T[K] => {
      return this.data[key];
    };
    set = (update: T): void => {
      //   this is like spread operator. it will take this.data obj and will overwrite with the update obj
      // ins tsconfig.json change target to Es6 to be able to use Object.assign()
      Object.assign(this.data, update);
    };
    getAll(): T {
      return this.data;
    }
  }
Run Code Online (Sandbox Code Playgroud)

<T> 指的是泛型类型。让我们初始化一个实例

 const myAttributes=new Attributes({name:"something",age:32})

 myAttributes.get("name")="something"
Run Code Online (Sandbox Code Playgroud)

注意这个语法

<K extends keyof T>
Run Code Online (Sandbox Code Playgroud)

为了能够使用它,我们应该注意两件事:

1- in typestring 字符串可以是一个类型。

2- javascript 中的所有对象属性本质上都是字符串。

当我们使用 get() 时,它接收的参数类型是传递给构造函数的对象的属性,并且由于对象属性是字符串并且字符串被允许是打字稿中的类型,我们可以使用它 <K extends keyof T>