2017-05-18 45 views
-8

當我運行下面的代碼,我得到的錯誤:爲什麼不能重新定義財產?

TypeError: Cannot redefine property: isBoolean

爲什麼我不能重新定義這些屬性?

function isBoolean() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "boolean") { 
 
    return true; 
 
    } else { 
 
    return false; 
 
    } 
 
} 
 

 
function isString() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "string") { 
 
    return true; 
 
    } else { 
 
    return false; 
 
    } 
 
} 
 

 
function isNumber() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (onoff) { 
 
    if (value === Infinity) { return Infinity; } 
 
    } 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "number") { 
 
    return true; 
 
    } else { 
 
    return false; 
 
    } 
 
} 
 

 
function isArray() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    return Array.isArray(value); 
 
} 
 

 
Object.defineProperties(window, { 
 
// "thisType" : { enumerable: false }, 
 
    "isBoolean": { enumerable: false }, 
 
    "isString" : { enumerable: false }, 
 
    "isNumber" : { enumerable: false }, 
 
    "isArray" : { enumerable: false }, 
 
});

+2

帖子都在這裏直接作爲文本代碼。切勿鏈接到代碼,*當然*從不鏈接到代碼圖片。 – Carcigenicate

+3

請發佈您的代碼,而不是鏈接到它的圖片。 – Bergi

+2

請參見[**我如何問一個很好的問題**](https://stackoverflow.com/help/how-to-ask)和[**如何創建一個最小的,完整的,並且可驗證例如** (https://stackoverflow.com/help/mcve) – Nope

回答

2

因爲一個全局函數聲明創建全局對象上,其configurable標誌爲false的結合(該窗口,在瀏覽器上)。這是覆蓋在GlobalDeclarationInstantiation,它使用CreateGlobalVarBinding以創建功能的結合,傳遞false作爲D標誌,它被用於configurable標誌。 (這是在步驟18.A,函數名是declaredVarNames的一部分,來自varDeclarations,其經由VarScopedDeclarations檢索,包括HoistableDeclaration S,其中之一是FunctionDeclaration。)

由於結合是不可配置的,你不能將它的enumerable標誌更改從truefalse

+0

但爲什麼呢?爲什麼我們不能刪除全局對象中的函數,而是將它們覆蓋爲未定義? –

+3

@Jonasw:你得問布蘭登·艾克,但我認爲這是因爲函數聲明實際上是相同的'var'聲明,當然除了他們有自己的價值馬上,它沒有任何意義(他),你會改變這些的基本屬性。但這是猜測。 –

+1

這是一個答案的隱藏寶石之一。如此詳細,並直接按規格。謝謝你的回答。 –

1

的問題是,當你在全局範圍內聲明的函數,它已與配置的標誌等於假其放到window對象上。要避免這種情況的一種方法是定義另一個函數內的功能(一個IIFE的偉大工程),像這樣:

你也應該設定內部Object.defineProperties()props對象的value財產,否則默認值爲undefined按文檔。

(function() { 
 
    'use strict'; 
 
    function isBoolean() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "boolean") { 
 
     return true; 
 
    } else { 
 
     return false; 
 
    } 
 
    } 
 

 
    function isString() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "string") { 
 
     return true; 
 
    } else { 
 
     return false; 
 
    } 
 
    } 
 

 
    function isNumber() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (onoff) { 
 
     if (value === Infinity) { return Infinity; } 
 
    } 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "number") { 
 
     return true; 
 
    } else { 
 
     return false; 
 
    } 
 
    } 
 

 
    function isArray() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    return Array.isArray(value); 
 
    } 
 

 
    Object.defineProperties(window, { 
 
    "isBoolean": { enumerable: false, value: isBoolean }, 
 
    "isString" : { enumerable: false, value: isString }, 
 
    "isNumber" : { enumerable: false, value: isNumber }, 
 
    "isArray" : { enumerable: false, value: isArray }, 
 
    }); 
 
})();

1

既然你把ecmascript-6標籤在你的問題,我可以建議你使用letconst與函數表達式?相反,函數語句/聲明(大致行爲就像var),與let/const聲明全局變量/常量不成爲(這裏window)全局對象的屬性。

const isBoolean = function() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "boolean") { 
 
    return true; 
 
    } else { 
 
    return false; 
 
    } 
 
}; 
 

 
const isString = function() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "string") { 
 
    return true; 
 
    } else { 
 
    return false; 
 
    } 
 
}; 
 

 
const isNumber = function() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    if (onoff) { 
 
    if (value === Infinity) { return Infinity; } 
 
    } 
 
    if (value===undefined || value===null) { return false; } 
 
    if (typeof(value) === "number") { 
 
    return true; 
 
    } else { 
 
    return false; 
 
    } 
 
}; 
 

 
const isArray = function() { 
 
    var value = arguments[0]; 
 
    if (!arguments.length) {return;} 
 
    return Array.isArray(value); 
 
}; 
 

 
console.log('"window" properties before "defineProperties":'); 
 
console.log('isBoolean: ' + ("isBoolean" in window)); 
 
console.log('isString: ' + ("isString" in window)); 
 
console.log('isNumber: ' + ("isNumber" in window)); 
 
console.log('isArray: ' + ("isArray" in window)); 
 

 
Object.defineProperties(window, { 
 
    "isBoolean": { enumerable: false }, 
 
    "isString" : { enumerable: false }, 
 
    "isNumber" : { enumerable: false }, 
 
    "isArray" : { enumerable: false }, 
 
}); 
 

 
console.log('"window" properties after "defineProperties":'); 
 
console.log('isBoolean: ' + ("isBoolean" in window)); 
 
console.log('isString: ' + ("isString" in window)); 
 
console.log('isNumber: ' + ("isNumber" in window)); 
 
console.log('isArray: ' + ("isArray" in window));

相關問題