تیم Chrome اخیراً اعلام کرد که ما در حال انتقال ویژگیهای DOM به زنجیره اولیه هستیم . این تغییر که در Chrome 43 پیادهسازی شده است - (بتا از اواسط آوریل 2015) - Chrome را با Web IDL Spec و سایر پیادهسازیهای مرورگرها مانند IE و Firefox مطابقت میدهد. ویرایش: روشنشده مرورگرهای قدیمیتر مبتنی بر WebKit، در حال حاضر با مشخصات سازگار نیستند، اما Safari اکنون سازگار است.
رفتار جدید از بسیاری جهات مثبت است. آن:
- سازگاری در سراسر وب را بهبود می بخشد (IE و فایرفاکس قبلاً این کار را انجام می دهند) از طریق مطابقت با مشخصات.
- به شما امکان می دهد به طور مداوم و کارآمد بر روی هر شیء DOM، گیرنده/ تنظیم کننده ایجاد کنید.
- قابلیت هک شدن برنامه نویسی DOM را افزایش می دهد. به عنوان مثال، به شما امکان میدهد که polyfills را پیادهسازی کنید که به شما امکان میدهد به طور موثر عملکردهایی را که در برخی از مرورگرها و کتابخانههای جاوا اسکریپت که رفتارهای ویژگی DOM پیشفرض را نادیده میگیرند، شبیهسازی کنید.
به عنوان مثال، یک مشخصات فرضی W3C شامل برخی عملکردهای جدید به نام isSuperContentEditable
است و مرورگر کروم آن را پیادهسازی نمیکند، اما میتوان این ویژگی را با یک کتابخانه «polyfill» یا شبیهسازی کرد. به عنوان توسعهدهنده کتابخانه، طبیعتاً میخواهید از prototype
به صورت زیر برای ایجاد یک polyfill کارآمد استفاده کنید:
Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
get: function() { return true; },
set: function() { /* some logic to set it up */ },
});
قبل از این تغییر - برای سازگاری با سایر ویژگیهای DOM در کروم - باید ویژگی جدید را در هر نمونه ایجاد میکردید، که برای هر HTMLDivElement
در صفحه بسیار ناکارآمد خواهد بود.
این تغییرات برای سازگاری، عملکرد و استانداردسازی پلتفرم وب مهم هستند، اما می توانند مشکلاتی را برای توسعه دهندگان ایجاد کنند. اگر به دلیل سازگاری قدیمی بین Chrome و WebKit به این رفتار متکی بودید، توصیه می کنیم سایت خود را بررسی کنید و خلاصه تغییرات را در زیر مشاهده کنید.
خلاصه تغییرات
استفاده از hasOwnProperty
در یک نمونه DOM Object اکنون false
برمیگرداند
گاهی اوقات توسعه دهندگان از hasOwnProperty
برای بررسی وجود یک ویژگی در یک شی استفاده می کنند. این دیگر طبق مشخصات کار نخواهد کرد زیرا ویژگیهای DOM اکنون بخشی از زنجیره اولیه هستند و hasOwnProperty
فقط اشیاء فعلی را بررسی میکند تا ببیند آیا روی آن تعریف شده است یا خیر.
قبل از Chrome 42 و شامل موارد زیر true
.
> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");
true
در Chrome 43 به بعد، false
برمیگردد.
> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");
false
اکنون این بدان معناست که اگر می خواهید بررسی کنید که isContentEditable
در عنصر موجود است، باید نمونه اولیه را در شی HTMLElement بررسی کنید. به عنوان مثال HTMLDivElement
از HTMLElement
که خاصیت isContentEditable
را تعریف می کند به ارث می برد.
> HTMLElement.prototype.hasOwnProperty("isContentEditable");
true
شما قفل استفاده از hasOwnProperty
را ندارید. توصیه میکنیم از عملوند بسیار سادهتر in
عملوند استفاده کنید، زیرا این ویژگی کل زنجیره نمونه اولیه را بررسی میکند.
if("isContentEditable" in div) {
// We have support!!
}
Object.getOwnPropertyDescriptor در DOM Object Instance دیگر توصیفگر خاصیت را برای ویژگی ها بر نمی گرداند.
اگر سایت شما نیاز به دریافت توصیفگر ویژگی برای یک ویژگی در یک شی DOM دارد، اکنون باید زنجیره اولیه را دنبال کنید.
اگر میخواهید توضیحات دارایی را در Chrome 42 و قبل از آن دریافت کنید، باید این کار را انجام دهید:
> Object.getOwnPropertyDescriptor(div, "isContentEditable");
Object {value: "", writable: true, enumerable: true, configurable: true}
Chrome 43 به بعد در این سناریو undefined
باز خواهد گشت.
> Object.getOwnPropertyDescriptor(div, "isContentEditable");
undefined
به این معنی که اکنون برای دریافت توصیفگر ویژگی برای ویژگی isContentEditable
، باید زنجیره اولیه را به صورت زیر دنبال کنید:
> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");
Object {get: function, set: function, enumerable: false, configurable: false}
JSON.stringify دیگر ویژگی های DOM را سریالی نمی کند
JSON.stringify
ویژگی های DOM را که در نمونه اولیه هستند سریال نمی کند. برای مثال، اگر میخواهید شیای مانند Push Notification's PushSubscription را سریالسازی کنید، میتواند بر سایت شما تأثیر بگذارد.
Chrome 42 و قبل از آن، موارد زیر کار میکردند:
> JSON.stringify(subscription);
{
"endpoint": "https://something",
"subscriptionId": "SomeID"
}
Chrome 43 به بعد خصوصیاتی را که در نمونه اولیه تعریف شده است سریال نمی کند و یک شی خالی به شما برگردانده می شود.
> JSON.stringify(subscription);
{}
شما باید روش سریال سازی خود را ارائه دهید، به عنوان مثال می توانید موارد زیر را انجام دهید:
function stringifyDOMObject(object)
{
function deepCopy(src) {
if (typeof src != "object")
return src;
var dst = Array.isArray(src) ? [] : {};
for (var property in src) {
dst[property] = deepCopy(src[property]);
}
return dst;
}
return JSON.stringify(deepCopy(object));
}
var s = stringifyDOMObject(domObject);
نوشتن در ویژگی های فقط خواندنی در حالت سخت باعث ایجاد خطا می شود
زمانی که از حالت سخت استفاده می کنید، قرار است نوشتن در ویژگی های فقط خواندنی یک استثنا ایجاد کند. برای مثال موارد زیر را در نظر بگیرید:
function foo() {
"use strict";
var d = document.createElement("div");
console.log(d.isContentEditable);
d.isContentEditable = 1;
console.log(d.isContentEditable);
}
کروم 42 و قبل از آن، این عملکرد ادامه مییابد و بیصدا به اجرای عملکرد ادامه میدهد، اگرچه isContentEditable
تغییر نمیکند.
// Chrome 42 and earlier behavior
> foo();
false // isContentEditable
false // isContentEditable (after writing to read-only property)
اکنون در کروم 43 و به بعد یک استثنا وجود خواهد داشت.
// Chrome 43 and onwards behavior
> foo();
false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter
من یک مشکل دارم، باید چه کار کنم؟
راهنمایی را دنبال کنید یا در زیر نظر بگذارید و بیایید صحبت کنیم.
من سایتی رو دیدم که مشکل داره چیکار کنم؟
سوال عالی اکثر مشکلات مربوط به سایتها بر اساس این واقعیت است که یک سایت برای تشخیص حضور ویژگی با روش getOwnProperty
انتخاب کرده است، این اغلب زمانی انجام میشود که مالک سایت فقط مرورگرهای قدیمی WebKit را هدف قرار داده باشد. چند کار وجود دارد که یک توسعه دهنده می تواند انجام دهد:
- مشکلی در مورد سایت آسیب دیده در ردیاب مشکل ما (Chrome) ثبت کنید
- مشکل را در رادار WebKit و مرجع https://bugs.webkit.org/show_bug.cgi?id=49739 ثبت کنید
من به طور کلی علاقه مند به دنبال کردن این تغییر هستم
- اشکال اصلی 2010: https://bugs.chromium.org/p/chromium/issues/detail?id=43394 - توجه: بیشتر کارها روی آن است.
- بررسی کد برای commit