이제 DOM 속성이 프로토타입 체인에 추가됨

Chrome팀에서는 최근 DOM 속성을 프로토타입 체인으로 이전한다고 발표했습니다. Chrome 43(2015년 4월 중순 베타 버전)에서 구현되는 이번 변경사항으로 Web IDL 사양 및 IE, Firefox와 같은 다른 브라우저의 구현에 맞춰 Chrome이 더욱 강력해졌습니다. 수정: 설명됨 이전 WebKit 기반 브라우저는 현재 사양과 호환되지 않지만 Safari는 현재 호환됩니다.

새로운 행동은 여러 면에서 긍정적입니다. 담고 있습니다.

  • 사양을 준수하여 웹 (IE 및 Firefox에서 이미 사용 중)의 호환성을 개선합니다.
  • 모든 DOM 객체에 getter/setter를 일관되고 효율적으로 만들 수 있습니다.
  • DOM 프로그래밍의 해킹 가능성을 높입니다. 예를 들어, 기본 DOM 특성 동작을 재정의하는 일부 브라우저와 JavaScript 라이브러리에서 누락된 기능을 효율적으로 에뮬레이션할 수 있는 폴리필을 구현할 수 있습니다.

예를 들어 가상의 W3C 사양에 isSuperContentEditable라는 새 기능이 포함되어 있는데 Chrome 브라우저는 이를 구현하지 않지만 '폴리필'은 가능합니다. 에뮬레이션할 수 있습니다 라이브러리 개발자는 당연히 효율적인 폴리필을 만들기 위해 다음과 같이 prototype를 사용하는 것이 좋습니다.

Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
    get: function() { return true; },
    set: function() { /* some logic to set it up */ },
});

이 변경사항이 적용되기 전에는 Chrome의 다른 DOM 속성과의 일관성을 위해 모든 인스턴스에서 새 속성을 만들어야 했으며, 이 경우 페이지의 모든 HTMLDivElement에 대해 매우 비효율적입니다.

이러한 변경사항은 웹 플랫폼의 일관성, 성능, 표준화를 위해 중요하지만 개발자에게는 몇 가지 문제를 일으킬 수 있습니다. Chrome과 WebKit 간의 기존 호환성 때문에 이 동작에 의존하고 있었다면 사이트를 확인하고 아래 변경사항 요약을 확인하시기 바랍니다.

변경사항 요약

이제 DOM 객체 인스턴스에서 hasOwnProperty를 사용하면 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 객체에서 프로토타입을 확인해야 합니다. 예를 들어 HTMLDivElementisContentEditable 속성을 정의하는 HTMLElement에서 상속받습니다.

> HTMLElement.prototype.hasOwnProperty("isContentEditable");

true

hasOwnProperty 사용이 제한되지 않습니다. 전체 프로토타입 체인의 속성을 확인하므로 훨씬 간단한 in 피연산자를 사용하는 것이 좋습니다.

if("isContentEditable" in div) {
    // We have support!!
}

DOM 객체 인스턴스의 Object.getOwnPropertyDescriptor가 더 이상 속성의 속성 설명어를 반환하지 않습니다.

사이트에서 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 속성을 직렬화하지 않습니다. 예를 들어 푸시 알림의 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);
}

Chrome 42 및 이전 버전에서는 isContentEditable가 변경되지 않았지만 이 함수는 함수를 실행할 때 조용히 전달되었습니다.

// Chrome 42 and earlier behavior
> foo();

false // isContentEditable
false // isContentEditable (after writing to read-only property)

이제 Chrome 43 이상에서는 예외가 발생합니다.

// Chrome 43 and onwards behavior
> foo();

false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter

문제가 있습니다. 어떻게 해야 하나요?

안내를 따르거나 아래에 댓글을 남겨 토론해 보세요.

문제가 있는 사이트를 발견했습니다. 어떻게 해야 하나요?

좋은 질문이에요. 사이트에서 발생하는 대부분의 문제는 사이트에서 getOwnProperty 메서드를 사용하여 속성 접속 감지를 수행하도록 선택했다는 사실을 기반으로 발생합니다. 이 문제는 주로 사이트 소유자가 이전 WebKit 브라우저만 타겟팅한 경우에 발생합니다. 개발자는 다음과 같은 몇 가지 작업을 할 수 있습니다.

  • (Chrome) Issue Tracker에서 영향을 받은 사이트에 대한 문제를 신고합니다.
  • WebKit 레이더에서 문제를 신고하고 https://bugs.webkit.org/show_bug.cgi?id=49739 페이지를 참조합니다.

전반적으로 이 변경사항을 따르는 데 관심이 있음