خصوصی در مقابل #خصوصی – انجمن DEV

Summarize this content to 400 words in Persian Lang
مقدمه (با نام مستعار شما می توانید این قسمت را نادیده بگیرید)چند هفته پیش در محل کار حواس من پرت شد و به طور تصادفی این وبلاگ را به عنوان یک مطلب نوشتم src/readme.md. اکنون که میخواهم آن شاخه را در زمان خودش ادغام کنم تا آن readme را حذف کنم، اما دوست دارم فکر کنم که بیش از 4 نفر دیگر در تیم من ممکن است این دیدگاه جالب باشد. بنابراین اکنون آن را همانطور که هست به شما ارائه می کنم. کد نویسی مبارک!
سلام
تصمیم گرفتم قراردادی را که در این پروژه در مورد سبک TypeScript خصوصی و سبک خصوصی ECMAScript استفاده میکردم، یادداشت کنم.
class Foo {
private bar: string;
constructor() {
this.bar = ‘secret sauce’;
}
}
console.log(new Foo().bar); // TypeScript error
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در TypeScript می توانید از private کلمه کلیدی برای علامت گذاری فیلدها، ویژگی ها و متدها به عنوان “خصوصی” (فقط از داخل همان کلاس قابل دسترسی است).با این حال، هنگامی که این کد کامپایل شد، این محدودیت دیگر وجود ندارد زیرا private بخشی از جاوا اسکریپت نیست.
بسته به پیکربندی TypeScript شما، کامپایلر هر دو از سوء استفاده از فیلد خصوصی شکایت خواهد کرد. اما هنوز هم کامپایل و کد زیر را منتشر کنید.
class Foo {
constructor() {
this.bar = ‘secret sauce’;
}
}
console.log(new Foo().bar); // logs “secret sauce”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
گزینه جایگزین استفاده از اصلاحکننده خصوصی ECMAScript است که با پیشوند نام با هش انجام میشود. #.
class Foo {
#bar: string;
constructor() {
this.#bar = ‘secret sauce’;
}
}
console.log(new Foo().#bar); // TypeScript error
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این سبک یک “حوزه خصوصی واقعی” است به این معنا که حریم خصوصی توسط موتور جاوا اسکریپت در زمان اجرا اعمال می شود.
class Foo {
constructor() {
this.#bar = ‘secret sauce’;
}
}
console.log(new Foo().#bar); // JavaScript error
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در پیکربندی پروژه ما، استفاده اشتباه از هر یک منجر به خطای کامپایل و خط قرمز عصبانی در VSCode می شود.این سوال پیش می آید که از کدام یک استفاده کنیم؟ اگر هر دو کار می کنند و تا آنجا که به ما مربوط می شود یک کار را انجام می دهند، نباید مهم باشد. این (بیشتر) به یک موضوع ترجیح شخصی برمی گردد.
در طول توسعه این پروژه (و سایر پروژه های شخصی) من بر روی قرارداد زیر توافق کرده ام.
class ClickLogger {
#clickCount: number;
get clickCount(): number {
return this.#clickCount;
}
constructor() {
this.#clickCount = 0;
document.body.addEventListener(‘click’, this.#handleClick);
}
private logClickAtLocation(x: number, y: number): void {
this.#clickCount++;
console.log(
`${nth(this.clickCount)} click detected! Clicked at ${x}, ${y}`,
);
}
#handleClick = (e: MouseEvent) => {
this.logClickAtLocation(e.clientX, e.clientY);
};
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
توجه داشته باشید: اجرای nth برای مثال مهم نیست اما به هر حال آن را در زیر آورده ام.
کنوانسیون را می توان به صورت زیر تعریف کرد:
اگر روش محدود است، از ES private استفاده کنید
اگر یک فیلد پشتیبان دارایی است، از ES private استفاده کنید
در غیر این صورت از TypeScript private استفاده کنید
اگر روش محدود است، از ES private استفاده کنید
مقدار بازگردانده شده توسط جاوا اسکریپت this کلمه کلیدی همیشه در زمان نوشتن یک تابع یا روش شناخته شده نیست.این به این دلیل است که مقدار فقط زمانی تنظیم می شود که تابع یا متد فراخوانی شود.بهترین راه برای فکر کردن this به عنوان یک پارامتر مخفی برای هر تابع است و جاوا اسکریپت بسته به نحوه فراخوانی آن تصمیم می گیرد که چه مقداری را در آنجا قرار دهد.
بنابراین وقتی کدی را می نویسید که شبیه این است
function printThis() {
console.log(this);
}
const obj = {
foo: ‘bar’,
printThis,
};
printThis();
obj.printThis();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
چیزی که دریافت می کنید کدی است که به این صورت اجرا می شود*
توجه داشته باشید: این فرض را بر این میگذارد که کامپایلر TypeScript شما از “حالت سخت” استفاده میکند (در ادامه در مورد آن بیشتر توضیح خواهیم داد)
function printThis(this: unknown) {
console.log(this);
}
const obj = {
foo: ‘bar’,
printThis,
};
printThis(undefined); // logs “undefined”
obj.printThis(obj); // logs “{foo: ‘bar’, printThis: f}”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
به طور کلی، ارزش استفاده شده برای this را می توان توسط به سمت چپ نقطه نگاه می کنم. اگر نقطه وجود نداشته باشد، undefined استفاده می شود.
printThis();
\- there’s no dot, so `undefined` is used
obj.printThis()
|-|
– Left of the dot is “obj” so “obj” is passed as `this`
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این برای هر نوع “چپ نقطه” کار می کند.
something().list[4].printThis();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
تبدیل می شود
const _ = something().list[4];
_.printThis(_);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
توجه داشته باشید: something().list[4] فقط یک بار ارزیابی می شود
استثناها: 'استفاده از سختگیرانه':
من در بالا در مورد فرض “حالت دقیق” اشاره کردم. حالت سخت جاوا اسکریپت رفتار را کمی تغییر می دهد. در موردی که “سمت چپ نقطه” وجود ندارد، جاوا اسکریپت در واقع از مقدار استفاده می کند globalThis، که در مرورگرها اشاره ای به جهانی است Window شی فقط در حالت سخت از آن استفاده می کند undefined. تمرین خوبی است که همیشه از حالت سخت استفاده کنید زیرا تعدادی از چیزها را بهینه می کند تا رفتار زمان اجرا را قابل پیش بینی تر و (بنابراین) ایمن تر کند، اما برای کامل بودن، در اینجا یک مثال آورده شده است:
function printStrict() {
‘use strict’;
console.log(this);
}
function printLoose() {
console.log(this);
}
printStrict(); // logs “undefined”
printLoose(); // logs “Window {…}”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
همه کدهای موجود در این readme فرض میکنند که حالت سخت فعال است.
استثناها: روش های محدود
همچنین امکان بارگذاری یک تابع با مقدار for وجود دارد this (فکر کنید تابع currying) با استفاده از .bind روش
function printThis() {
console.log(this);
}
const message = ‘Abra kadabra’;
const boundPrint = printThis.bind(message);
printThis(); // undefined
boundPrint(); // “Abra kadabra”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
استثناها: توابع پیکان
یک تابع فلش (با نام مستعار عبارت lambda) از فلش استفاده می کند => توکن برای ایجاد یک تابع ناشناس کوچک.
const printThis = () => console.log(this);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ارزش از this کلمه کلیدی داخل یک تابع فلش تنظیم شده است در لحظه ایجاد تابع. به عبارت دیگر، تقریباً معادل موارد زیر است:
const printThis = function () {
return console.log(this);
}.bind(this);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ارزش از this داخل تابع از هر چیزی که در زمان ایجاد تابع بوده است به ارث می رسد.
حالا که می دانیم چگونه this آثار (درست است؟) می توانم به اصل مطلب برسم… تقریبا.
(بیشتر) توابع Callback به گونه ای فراخوانی می شوند که اختصاص دهند undefined به this. این بدان معنی است که کد زیر کار نخواهد کرد
class ClickLogger {
private clicks = 0;
constructor() {
document.body.addEventListener(‘click’, this.logClick);
}
private logClick() {
this.clicks++;
console.log(`Clicked ${this.clicks} times`);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
هنگامی که امیتر رویداد ما را فراخوانی می کند logClick روش این کار را به این صورت انجام می دهد
class EventEmitter {
// …
emitEvent(e) {
for (const handler of this.handlers) {
handler(e);
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
پس وقتی می دویم this.clicks++ ما یک خطا دریافت می کنیم زیرا this دارای ارزش است undefined.
برای رفع این مشکل باید یک متد محدود ایجاد کنیم. سه راه برای انجام این کار وجود دارد:
از یک جدید ساخته شده استفاده کنید .bind روش
document.body.addEventListener(‘click’, this.logClick.bind(this));
این تا حدی لفظی است اما کار می کند.
استفاده مجدد از موجود .bind روش
class ClickLogger {
constructor() {
document.body.addEventListener(‘click’, this.logClick);
}
private logClick = function () {
// …
}.bind(this);
}
این حتی لفظ تر است، اما این مزیت را دارد که می توانید تماس بگیرید document.body.removeEventListener(‘click’, this.logClick) بعدا
از یک تابع پیکان جدید استفاده کنید
document.body.addEventListener(‘click’, (e) => this.logClick(e));
کوتاه ترین تا کنون اما از ناتوانی رنج می برد .removeEventListener مانند مثال 1.
از یک تابع پیکان موجود استفاده کنید
class ClickLogger {
constructor() {
document.body.addEventListener(‘click’, this.logClick);
}
private logClick = () => {
//…
};
}
IMO این یکی تمیزترین است. این روش خیلی طولانی تر از یک روش معمولی نیست، بلکه ارزش آن را نشان می دهد this به دلیل اینکه به عنوان یک تابع فلش تعریف شده است و می توان از آن استفاده کرد .removeEventListener.
اکنون تصمیم گرفته ام که گزینه 4 بالا را دوست دارم، اما یک مشکل دیگر دارم. تشخیص اینکه کدام روش ها مقید هستند و کدام نه آسان نیست:
class ClickLogger {
constructor() {
document.body.addEventListener(‘click’, this.logClick);
document.body.addEventListener(‘keydown’, this.resetCount);
}
// Somewhere else in the file possibly off screen
private logClick = () => {
// …
};
private resetCount() {
// …
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
resetCount مقید نیست؛ اوه، حالا کد شما کار نمی کند.
بنابراین برای متدهای باند من دوست دارم از ES private استفاده کنم # برای و روشهای بیقید من از TypeScript private استفاده میکنم. این یک شکل از نشانه گذاری مجارستانی است.
اگر یک فیلد پشتیبان دارایی است، از ES private استفاده کنید
class ClickCounter {
#clickCount: number;
get clickCount() {
return this.#clickCount;
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
هر دو #clickCount و clickCount دادههای مشابهی را نشان میدهند، اما نمیتوانیم با TypeScript خصوصی به هر دو نام یکسان بدهیم، زیرا زمانی که کامپایل شد private از بین می رود و در نهایت دو بار همان خاصیت می شود.
class ClickCounter {
private clickCount: number; // error: duplicate identifier
get clickCount() {
return this.clickCount;
} // error: duplicate identifier
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بنابراین اگر باید یک نام جدید کمی متفاوت انتخاب کنیم، چرا نامی را انتخاب نکنیم که با نحوه کار خود جاوا اسکریپت همسو باشد.
در غیر این صورت از TypeScript private استفاده کنید
این مقاله من را به پایان می رساند. ممنون از وقتی که گذاشتید.
تقریباً فراموش کردم که یک تفاوت بین آنها را ذکر کنم private و # هنگام استفاده از Vue
class Counter {
#count: number;
get count() {
return this.#count;
}
increment() {
this.#count++;
}
}
const c = ref(new Counter());
c.value.increment(); // ERROR, cannot access private variable #count from outside the class it was defined in
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
Ref ها در Vue مقادیر خود را در a قرار می دهند Proxy شی، بنابراین شما چیزی شبیه به این به نظر می رسد
const c = {
value: new Proxy(new Counter(), {
get: (target, key) => {
return target[key];
},
}),
};
c.value.increment();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون مقدار “سمت چپ نقطه” در واقع همان است Proxy شیء، نه Counter. این increment سپس تابع بر روی فراخوانی می شود Proxy و از آنجایی که #count خصوصی است برای Counter تلاش برای دسترسی به آن به خطا تبدیل می شود. shallowRef نیز این مشکل را دارد اگر اینطور فکر می کنید می توانید خودتان تصمیم بگیرید Proxies ضد الگو هستند
برای دور زدن این می توانید useRaw(c.value).increment() اما این زشت است و با توجه به آن refs در همه جا استفاده می شود، خسته کننده و پر سر و صدا می شود.
شما همچنین می توانید استفاده کنید private زیرا در سرزمین جاوا اسکریپت private واقعا “خصوصی” نیست.
پایان.
function nth(n: number) {
const str = n.toFixed(0);
if (str.slice(-2, -1) === ‘1’) return `${str}th`;
switch (n % 10) {
case 1:
return `${str}st`;
case 2:
return `${str}nd`;
case 3:
return `${str}rd`;
default:
return `${str}th`;
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مقدمه (با نام مستعار شما می توانید این قسمت را نادیده بگیرید)
چند هفته پیش در محل کار حواس من پرت شد و به طور تصادفی این وبلاگ را به عنوان یک مطلب نوشتم
src/readme.md
. اکنون که میخواهم آن شاخه را در زمان خودش ادغام کنم تا آن readme را حذف کنم، اما دوست دارم فکر کنم که بیش از 4 نفر دیگر در تیم من ممکن است این دیدگاه جالب باشد. بنابراین اکنون آن را همانطور که هست به شما ارائه می کنم. کد نویسی مبارک!
سلام
تصمیم گرفتم قراردادی را که در این پروژه در مورد سبک TypeScript خصوصی و سبک خصوصی ECMAScript استفاده میکردم، یادداشت کنم.
class Foo {
private bar: string;
constructor() {
this.bar = 'secret sauce';
}
}
console.log(new Foo().bar); // TypeScript error
در TypeScript می توانید از private
کلمه کلیدی برای علامت گذاری فیلدها، ویژگی ها و متدها به عنوان “خصوصی” (فقط از داخل همان کلاس قابل دسترسی است).
با این حال، هنگامی که این کد کامپایل شد، این محدودیت دیگر وجود ندارد زیرا private
بخشی از جاوا اسکریپت نیست.
بسته به پیکربندی TypeScript شما، کامپایلر هر دو از سوء استفاده از فیلد خصوصی شکایت خواهد کرد. اما هنوز هم کامپایل و کد زیر را منتشر کنید.
class Foo {
constructor() {
this.bar = 'secret sauce';
}
}
console.log(new Foo().bar); // logs "secret sauce"
گزینه جایگزین استفاده از اصلاحکننده خصوصی ECMAScript است که با پیشوند نام با هش انجام میشود. #
.
class Foo {
#bar: string;
constructor() {
this.#bar = 'secret sauce';
}
}
console.log(new Foo().#bar); // TypeScript error
این سبک یک “حوزه خصوصی واقعی” است به این معنا که حریم خصوصی توسط موتور جاوا اسکریپت در زمان اجرا اعمال می شود.
class Foo {
constructor() {
this.#bar = 'secret sauce';
}
}
console.log(new Foo().#bar); // JavaScript error
در پیکربندی پروژه ما، استفاده اشتباه از هر یک منجر به خطای کامپایل و خط قرمز عصبانی در VSCode می شود.
این سوال پیش می آید که از کدام یک استفاده کنیم؟ اگر هر دو کار می کنند و تا آنجا که به ما مربوط می شود یک کار را انجام می دهند، نباید مهم باشد. این (بیشتر) به یک موضوع ترجیح شخصی برمی گردد.
در طول توسعه این پروژه (و سایر پروژه های شخصی) من بر روی قرارداد زیر توافق کرده ام.
class ClickLogger {
#clickCount: number;
get clickCount(): number {
return this.#clickCount;
}
constructor() {
this.#clickCount = 0;
document.body.addEventListener('click', this.#handleClick);
}
private logClickAtLocation(x: number, y: number): void {
this.#clickCount++;
console.log(
`${nth(this.clickCount)} click detected! Clicked at ${x}, ${y}`,
);
}
#handleClick = (e: MouseEvent) => {
this.logClickAtLocation(e.clientX, e.clientY);
};
}
توجه داشته باشید: اجرای
nth
برای مثال مهم نیست اما به هر حال آن را در زیر آورده ام.
کنوانسیون را می توان به صورت زیر تعریف کرد:
- اگر روش محدود است، از ES private استفاده کنید
- اگر یک فیلد پشتیبان دارایی است، از ES private استفاده کنید
- در غیر این صورت از TypeScript private استفاده کنید
اگر روش محدود است، از ES private استفاده کنید
مقدار بازگردانده شده توسط جاوا اسکریپت this
کلمه کلیدی همیشه در زمان نوشتن یک تابع یا روش شناخته شده نیست.
این به این دلیل است که مقدار فقط زمانی تنظیم می شود که تابع یا متد فراخوانی شود.
بهترین راه برای فکر کردن this
به عنوان یک پارامتر مخفی برای هر تابع است و جاوا اسکریپت بسته به نحوه فراخوانی آن تصمیم می گیرد که چه مقداری را در آنجا قرار دهد.
بنابراین وقتی کدی را می نویسید که شبیه این است
function printThis() {
console.log(this);
}
const obj = {
foo: 'bar',
printThis,
};
printThis();
obj.printThis();
چیزی که دریافت می کنید کدی است که به این صورت اجرا می شود*
توجه داشته باشید: این فرض را بر این میگذارد که کامپایلر TypeScript شما از “حالت سخت” استفاده میکند (در ادامه در مورد آن بیشتر توضیح خواهیم داد)
function printThis(this: unknown) {
console.log(this);
}
const obj = {
foo: 'bar',
printThis,
};
printThis(undefined); // logs "undefined"
obj.printThis(obj); // logs "{foo: 'bar', printThis: f}"
به طور کلی، ارزش استفاده شده برای this
را می توان توسط به سمت چپ نقطه نگاه می کنم. اگر نقطه وجود نداشته باشد، undefined
استفاده می شود.
printThis();
\- there's no dot, so `undefined` is used
obj.printThis()
|-|
- Left of the dot is "obj" so "obj" is passed as `this`
این برای هر نوع “چپ نقطه” کار می کند.
something().list[4].printThis();
تبدیل می شود
const _ = something().list[4];
_.printThis(_);
توجه داشته باشید:
something().list[4]
فقط یک بار ارزیابی می شود
استثناها: 'استفاده از سختگیرانه':
من در بالا در مورد فرض “حالت دقیق” اشاره کردم. حالت سخت جاوا اسکریپت رفتار را کمی تغییر می دهد. در موردی که “سمت چپ نقطه” وجود ندارد، جاوا اسکریپت در واقع از مقدار استفاده می کند globalThis
، که در مرورگرها اشاره ای به جهانی است Window
شی فقط در حالت سخت از آن استفاده می کند undefined
. تمرین خوبی است که همیشه از حالت سخت استفاده کنید زیرا تعدادی از چیزها را بهینه می کند تا رفتار زمان اجرا را قابل پیش بینی تر و (بنابراین) ایمن تر کند، اما برای کامل بودن، در اینجا یک مثال آورده شده است:
function printStrict() {
'use strict';
console.log(this);
}
function printLoose() {
console.log(this);
}
printStrict(); // logs "undefined"
printLoose(); // logs "Window {...}"
همه کدهای موجود در این readme فرض میکنند که حالت سخت فعال است.
استثناها: روش های محدود
همچنین امکان بارگذاری یک تابع با مقدار for وجود دارد this
(فکر کنید تابع currying) با استفاده از .bind
روش
function printThis() {
console.log(this);
}
const message = 'Abra kadabra';
const boundPrint = printThis.bind(message);
printThis(); // undefined
boundPrint(); // "Abra kadabra"
استثناها: توابع پیکان
یک تابع فلش (با نام مستعار عبارت lambda) از فلش استفاده می کند =>
توکن برای ایجاد یک تابع ناشناس کوچک.
const printThis = () => console.log(this);
ارزش از this
کلمه کلیدی داخل یک تابع فلش تنظیم شده است در لحظه ایجاد تابع. به عبارت دیگر، تقریباً معادل موارد زیر است:
const printThis = function () {
return console.log(this);
}.bind(this);
ارزش از this
داخل تابع از هر چیزی که در زمان ایجاد تابع بوده است به ارث می رسد.
حالا که می دانیم چگونه this
آثار (درست است؟) می توانم به اصل مطلب برسم… تقریبا.
(بیشتر) توابع Callback به گونه ای فراخوانی می شوند که اختصاص دهند undefined
به this
. این بدان معنی است که کد زیر کار نخواهد کرد
class ClickLogger {
private clicks = 0;
constructor() {
document.body.addEventListener('click', this.logClick);
}
private logClick() {
this.clicks++;
console.log(`Clicked ${this.clicks} times`);
}
}
هنگامی که امیتر رویداد ما را فراخوانی می کند logClick
روش این کار را به این صورت انجام می دهد
class EventEmitter {
// ...
emitEvent(e) {
for (const handler of this.handlers) {
handler(e);
}
}
}
پس وقتی می دویم this.clicks++
ما یک خطا دریافت می کنیم زیرا this
دارای ارزش است undefined
.
برای رفع این مشکل باید یک متد محدود ایجاد کنیم. سه راه برای انجام این کار وجود دارد:
-
از یک جدید ساخته شده استفاده کنید
.bind
روشdocument.body.addEventListener('click', this.logClick.bind(this));
این تا حدی لفظی است اما کار می کند.
-
استفاده مجدد از موجود
.bind
روشclass ClickLogger { constructor() { document.body.addEventListener('click', this.logClick); } private logClick = function () { // ... }.bind(this); }
این حتی لفظ تر است، اما این مزیت را دارد که می توانید تماس بگیرید
document.body.removeEventListener('click', this.logClick)
بعدا -
از یک تابع پیکان جدید استفاده کنید
document.body.addEventListener('click', (e) => this.logClick(e));
کوتاه ترین تا کنون اما از ناتوانی رنج می برد
.removeEventListener
مانند مثال 1. -
از یک تابع پیکان موجود استفاده کنید
class ClickLogger { constructor() { document.body.addEventListener('click', this.logClick); } private logClick = () => { //... }; }
IMO این یکی تمیزترین است. این روش خیلی طولانی تر از یک روش معمولی نیست، بلکه ارزش آن را نشان می دهد
this
به دلیل اینکه به عنوان یک تابع فلش تعریف شده است و می توان از آن استفاده کرد.removeEventListener
.
اکنون تصمیم گرفته ام که گزینه 4 بالا را دوست دارم، اما یک مشکل دیگر دارم. تشخیص اینکه کدام روش ها مقید هستند و کدام نه آسان نیست:
class ClickLogger {
constructor() {
document.body.addEventListener('click', this.logClick);
document.body.addEventListener('keydown', this.resetCount);
}
// Somewhere else in the file possibly off screen
private logClick = () => {
// ...
};
private resetCount() {
// ...
}
}
resetCount
مقید نیست؛ اوه، حالا کد شما کار نمی کند.
بنابراین برای متدهای باند من دوست دارم از ES private استفاده کنم #
برای و روشهای بیقید من از TypeScript private استفاده میکنم. این یک شکل از نشانه گذاری مجارستانی است.
اگر یک فیلد پشتیبان دارایی است، از ES private استفاده کنید
class ClickCounter {
#clickCount: number;
get clickCount() {
return this.#clickCount;
}
}
هر دو #clickCount
و clickCount
دادههای مشابهی را نشان میدهند، اما نمیتوانیم با TypeScript خصوصی به هر دو نام یکسان بدهیم، زیرا زمانی که کامپایل شد private
از بین می رود و در نهایت دو بار همان خاصیت می شود.
class ClickCounter {
private clickCount: number; // error: duplicate identifier
get clickCount() {
return this.clickCount;
} // error: duplicate identifier
}
بنابراین اگر باید یک نام جدید کمی متفاوت انتخاب کنیم، چرا نامی را انتخاب نکنیم که با نحوه کار خود جاوا اسکریپت همسو باشد.
در غیر این صورت از TypeScript private استفاده کنید
این مقاله من را به پایان می رساند. ممنون از وقتی که گذاشتید.
تقریباً فراموش کردم که یک تفاوت بین آنها را ذکر کنم private
و #
هنگام استفاده از Vue
class Counter {
#count: number;
get count() {
return this.#count;
}
increment() {
this.#count++;
}
}
const c = ref(new Counter());
c.value.increment(); // ERROR, cannot access private variable #count from outside the class it was defined in
Ref ها در Vue مقادیر خود را در a قرار می دهند Proxy
شی، بنابراین شما چیزی شبیه به این به نظر می رسد
const c = {
value: new Proxy(new Counter(), {
get: (target, key) => {
return target[key];
},
}),
};
c.value.increment();
اکنون مقدار “سمت چپ نقطه” در واقع همان است Proxy
شیء، نه Counter
. این increment
سپس تابع بر روی فراخوانی می شود Proxy
و از آنجایی که #count
خصوصی است برای Counter
تلاش برای دسترسی به آن به خطا تبدیل می شود. shallowRef
نیز این مشکل را دارد اگر اینطور فکر می کنید می توانید خودتان تصمیم بگیرید Proxies
ضد الگو هستند
برای دور زدن این می توانید useRaw(c.value).increment()
اما این زشت است و با توجه به آن ref
s در همه جا استفاده می شود، خسته کننده و پر سر و صدا می شود.
شما همچنین می توانید استفاده کنید private
زیرا در سرزمین جاوا اسکریپت private
واقعا “خصوصی” نیست.
پایان.
function nth(n: number) {
const str = n.toFixed(0);
if (str.slice(-2, -1) === '1') return `${str}th`;
switch (n % 10) {
case 1:
return `${str}st`;
case 2:
return `${str}nd`;
case 3:
return `${str}rd`;
default:
return `${str}th`;
}
}