检索 document.cookie getter 和 setter

Retrieving document.cookie getter and setter

我正在尝试覆盖 document.cookie 因为我需要控制 cookie 创建,但似乎 getOwnPropertyDescriptor 在 document.cookie 上投射没有检索到它的 getter 和 setter(在 chrome 和 firefox 上试过)。有人可以向我解释这种行为吗?

https://jsfiddle.net/1363ktwp/7/

var obj={};

// creating a property using document.cookie descriptors
Object.defineProperty(
    obj, 
    "oldCookie",   
    Object.getOwnPropertyDescriptor(document, "cookie")
);
    
// setting cookies succesfully
document.cookie="test1=ok;path=/;expires=365;";
document.cookie="test2=ok;path=/;expires=365;";

alert(document.cookie);

Object.defineProperty(document, "cookie", {
    get: function () {
        return obj.oldCookie;
    },
    set: function (cookie) {
        /*
            ...preliminar operations
        */
        
        obj.oldCookie = cookie;
    }
});
    
// obj.oldCookie is just a string without getter/setter
// so assignments below doesn't works correctly
document.cookie="test3=ok;path=/;expires=365;";
document.cookie="test4=ok;path=/;expires=365;";

alert(document.cookie);

Could someone explain me this behaviour?

document.cookiehost object. Host objects are frequently not true JavaScript objects (called native objects 的 属性),既不需要也不保证具有 JavaScript 对象的特征。

事实上,如果许多甚至超过一两个浏览器使用 ES5 属性 getters/setters 实现 document.cookie,我会感到非常震惊。也许对于一些较新的 API(或者可能不是),但对于那些旧的 API,将会有很多麻烦。 (我还得考虑很长时间的安全后果...)

如果他们确实通过 ES5 getters/setters 实现了它,如果他们将其设为不可配置[=23],我也不会感到惊讶=] 属性(例如,您无法更改它)。

您可以使用 __lookupSetter____lookupGetter__ 方法,但请注意,它们已被弃用并且并非在任何地方都受支持。它们在 Chrome、Firefox、IE11 中正常工作。不要在 IE <10 中工作。 Opera 提供了这样的方法,但它们总是 return undefined。没有检查其他任何东西。

这是一个例子:

var cookieSetterOrig = document.__lookupSetter__("cookie");
var cookieGetterOrig = document.__lookupGetter__("cookie");
Object.defineProperty(document, "cookie", {
    get: function () {
        return cookieGetterOrig.apply(document);
    },
    set: function () {
        return cookieSetterOrig.apply(document, arguments);
    },
    configurable: true
});

原因

Object.getOwnPropertyDescriptor(document, 'cookie');

返回 undefinedgetOwnPropertyDescriptor 的工作方式:它不遍历原型链。

全局变量 document 包含实际继承自 Document.prototype:

的对象
Document.prototype.isPrototypeOf(document) // true

并且不拥有名为 "cookie" 的 属性,Document.prototype 拥有:

document.hasOwnProperty('cookie'); // false
Document.prototype.hasOwnProperty('cookie'); // true

检索 document.cookie 的描述符的一种方法是检索 Document.prototype.cookie 的描述符本身:

Object.getOwnPropertyDescriptor(Document.prototype, 'cookie');

称为 __lookupGetter____lookupSetter__ 的弃用函数实际上会遍历原型链,因此,您可以检索这些在 document 上调用它的方法,而不是 Document.prototype:

const cookieDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie');
cookieDescriptor.get === document.__lookupGetter__('cookie') // true