Object.assign的polyfill引起的思考

爲了向下兼容瀏覽器或者在不同的瀏覽器上使用新的特性,我們可以使用polyfill。昨天MDN上看完了Object.assign的polyfill,今天趁着中午休息的時間複寫了一下Object.assign的polyfill。

    Object.defineProperty(Object, 'assign', {
        value: function(target, sources) {
            if(target == null) {
                throw TypeError('Cannot convert undefined or null to Object');
            }

            target = new Object(target);
            var args = [].slice.call(arguments, 1);

            for(var index = 0; index < args.length; index++) {
                var source = args[index];
                if(source == null) continue;
                for(var key in source) {
                    if(Object.prototype.hasOwnProperty.call(source, key)) {
                        target[key] = source[key];
                    }
                }
            }

            return target;
        },
        writable: true,
        configurable: true
    });

簡單測試一下

    console.log(Object.assign({}, {a:1}));
    // => {a:1}
    console.log(Object.assign({}, {a:1}, undefined, null, 234));
    // => {a:1}
    console.log(Object.assign({}, {a:1, b:2}, '234'));
    // => { '0': '2', '1': '3', '2': '4', a: 1, b: 2 }
    console.log(Object.assign('123', {a:1, b:2}));
    // => { [String: '123'] a: 1, b: 2 }

看起來沒有問題 ,這時候突然來了想法,如果這樣寫結果是什麼樣的呢?

    console.log(Object.assign('123', '123'));
    // => Uncaught TypeError: Cannot assign to read only property '0' of object '[object String]'

ca,報錯了,我又去支持Object.assign的瀏覽器上試了下,也是報錯的。難道不可以這樣寫嗎?我又仔細看了下定義.

Object.assign()方法用於將所有可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。

Object.assign()在處理原始類型的時候會將它轉換成對象。但是看報錯的情況是屬性0是隻讀的

    console.log(Object.getOwnPropertyDescriptors(new Object('123')));
    // => 
    // 0: {value: "1", writable: false, enumerable: true, configurable: false}
    // 1: {value: "2", writable: false, enumerable: true, configurable: false}
    // 2: {value: "3", writable: false, enumerable: true, configurable: false}
    // length: {value: 3, writable: false, enumerable: false, configurable:false, ...}

string轉對象後是可迭代的,但是隻可讀 。所以我修改了下polyfill。

    Object.defineProperty(Object, 'assign', {
        value: function(target, sources) {
            if(target == null) {
                throw TypeError('Cannot convert undefined or null to Object');
            }

            target = new Object(target);
            var args = [].slice.call(arguments, 1);

            for(var index = 0; index < args.length; index++) {
                var source = args[index];
                if(source == null) continue;
                for(var key in source) {
                    var isKeyWritable = Object.prototype.hasOwnProperty.call(target, key)?Object.getOwnPropertyDescriptor.call
                    (target, key):true;
                    if(Object.prototype.hasOwnProperty.call(source, key) && isKeyWritable) 
                        {    
                            console.log(isKeyWritable);
                            target[key] = source[key];
                        }
                }
            }

            return target;
        },
        writable: true,
        configurable: true
    });

再試一下

    console.log(Object.assign('123', '123'));
    // => [String: '123']
    console.log(Object.assign('123', '1234'));
    // => { [String: '123'] '3': '4' }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章