الاستدعاء والتعيين في TypeScript
أنا أحاول إنشاء طريقتي الحصول والتعيين لخاصية:
private _name: string;
Name() {
get:
{
return this._name;
}
set:
{
this._name = ???;
}
}
ما هي الكلمة المفتاحية لتعيين قيمة؟
الإجابة رقم 1
يستخدم TypeScript صياغة getter/setter التي تشبه ECMAScript4/ActionScript3.
class foo {
private _bar: boolean = false;
get bar(): boolean {
return this._bar;
}
set bar(value: boolean) {
this._bar = value;
}
}
ومع ذلك، من أجل استخدامه على الإطلاق، يجب عليك التأكد من أن مُركّب TypeScript يستهدف ECMAScript5 أو أعلى. إذا كنت تستخدم مُركّب سطر الأوامر، فاستخدم العلم --target بهذا الشكل:
tsc --target ES5
إذا كنت تستخدم Visual Studio، يجب عليك تعديل ملف المشروع الخاص بك لإضافة العلامة إلى التكوين لأداة البناء TypeScriptCompile. يمكنك رؤية ذلك هنا:
سيؤدي ذلك إلى إنتاج هذا الجافاسكريبت، باستخدام ميزة Object.defineProperty() في ECMAScript 5.
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;
})();
الإصدارات الأحدث من EcmaScript ستنتج شفرة تبدو أكثر شبهاً بـ TypeScript الأصلي. على سبيل المثال، استهداف EcmaScript2017 سينتج:
"use strict";
class foo {
constructor() {
this._bar = false;
}
get bar() {
return this._bar;
}
set bar(value) {
this._bar = value;
}
}
لذا لاستخدامه،
var myFoo = new foo();
if(myFoo.bar) { // calls the getter
myFoo.bar = false; // calls the setter and passes false
}
كما يقترح @DanFromGermany أدناه، إذا كنت ببساطة تقرأ وتكتب خاصية محلية مثل foo.bar=true، فإن وجود زوج من الدوال setter و getter هو أمر مبالغ فيه. يمكنك دائمًا إضافتها لاحقًا إذا كنت تحتاج إلى القيام بشيء ما، مثل تسجيل الأحداث، كلما تم قراءة الخاصية أو كتابتها.
يمكن استخدام الدوال المستقبلة (Getters) لتنفيذ الخصائص للقراءة فقط. هنا مثال يوضح أيضًا كيفية تفاعل الدوال المستقبلة مع الخصائص للقراءة فقط والأنواع الاختيارية.
//
// type with optional readonly property.
// baz?:string is the same as baz:string|undefined
//
type Foo = {
readonly bar: string;
readonly baz?: string;
}
const foo:Foo = {bar: "bar"}
console.log(foo.bar) // prints 'bar'
console.log(foo.baz) // prints undefined
//
// interface with optional readonly property
//
interface iFoo {
readonly bar: string;
readonly baz?: string;
}
const ifoo:iFoo = {bar: "bar"}
console.log(ifoo.bar) // prints 'bar'
console.log(ifoo.baz) // prints undefined
//
// class implements bar as a getter,
// but leaves off baz.
//
class iBarClass implements iFoo {
get bar() { return "bar" }
}
const iBarInstance = new iBarClass()
console.log(iBarInstance.bar) // prints 'bar'
console.log(iBarInstance.baz) // prints 'undefined'
// accessing baz gives warning that baz does not exist
// on iBarClass but returns undefined
// note that you could define baz as a getter
// and just return undefined to remove the warning.
//
// class implements optional readonly property as a getter
//
class iBazClass extends iBarClass {
private readonly _baz?: string
constructor(baz?:string) {
super()
this._baz = baz
}
get baz() { return this._baz; }
}
const iBazInstance = new iBazClass("baz")
console.log(iBazInstance.bar) // prints bar
console.log(iBazInstance.baz) // prints baz
الإجابة رقم 2
لقد قدم إزورد إجابة جيدة بالفعل، لكن لاحظت أن أحد التعليقات يسأل عن كيفية استخدامه. بالنسبة للأشخاص مثلي الذين يصادفون هذا السؤال، فكرت أنه سيكون من المفيد وجود رابط إلى الوثائق الرسمية حول getters و setters على موقع TypeScript لأن ذلك يشرحها جيدًا، ومن المؤمل أن يبقى دائمًا محدثًا مع إجراء التغييرات، ويظهر أمثلة على الاستخدام:
http://www.typescriptlang.org/docs/handbook/classes.html
على وجه الخصوص، لأولئك الذين ليسوا مألوفين به، لاحظ أنه لا يتم دمج كلمة 'get' في استدعاء getter (وبالمثل بالنسبة للـ setters):
var myBar = myFoo.getBar(); // wrong
var myBar = myFoo.get('bar'); // wrong
يجب أن تفعل هذا ببساطة:
var myBar = myFoo.bar; // correct (get)
myFoo.bar = true; // correct (set) (false is correct too obviously!)
معطى فصل مثل:
class foo {
private _bar:boolean = false;
get bar():boolean {
return this._bar;
}
set bar(theBar:boolean) {
this._bar = theBar;
}
}
سيتم بعد ذلك استدعاء الدالة 'bar' الخاصة بالحصول على الخاصية الخاصة '_bar'.
الإجابة رقم 3
إليك مثال عملي يجب أن يوجهك في الاتجاه الصحيح:
class Foo {
_name;
get Name() {
return this._name;
}
set Name(val) {
this._name = val;
}
}
المعاملات getter و setter في جافاسكريبت هي مجرد دوال عادية. الـ setter هو دالة تأخذ معلمة تكون قيمتها هي القيمة التي يتم تعيينها.
الإجابة رقم 4
يمكنك كتابة هذا
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;
}
}
