只要塊級作用域存在let命令,它所聲明的變量就“綁定”這個區域,不再受外部的影響。這么說可能有些抽象,舉個例子:
var temp = 123;if(true) { console.log(temp); let temp;}結果:
> ReferenceError: temp is not defined
在代碼塊內,使用let聲明變量之前,該變量都是不可用的。在語法上,稱為“暫時性死區”。(temporal dead zone)
ES6規定暫時性死區和let、const語句不出現變量提升,主要是為了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行為。
這兩個方法都可以改變一個函數的上下文對象,只是接受參數的方式不一樣。
call接收的是逗號分隔的參數。
apply接收的是參數列表。
相信你肯定看到過這樣的代碼:
var arr = [1, 2, 3];var max = Function.prototype.apply.call(Math.max, null, arr);console.log(max); // 3
那么對這段代碼怎么理解呢?
1.將Function.prototype.apply看成一個整體
(Function.prototype.apply).call(Math.max, null, arr)
2.func.call(context, args)可以轉化為context.func(args)
所以代碼被轉換為:
Math.max.apply(undefined, arr)
基本上到這一步已經沒必要去解釋了。
那么你有沒有試過將call和apply互換位置呢?
var arr = [1, 2, 3];var max = Function.prototype.call.apply(Math.max, null, arr);console.log(max); // -Infinity
為什么的它的輸出結果為-Infinity呢?
因為apply的第二參數必須為數組,這里并不是,所以參數不能正確的傳遞給call函數。
根據func.apply(context, args)可以轉化為context.func(args)。所以被轉化成了Math.max.call(), 直接調用則會輸出-Infinity。
如果想要正確調用,則應這樣書寫:
var arr = [1, 2, 3];var max = Function.prototype.call.apply(Math.max, arr);console.log(max); // 3
為了鞏固以上內容,且看一個面試題:
var a = Function.prototype.call.apply(function(a){return a;}, [0,4,3]);alert(a); 分析彈出的a值為多少?
// 將call方法看成一個整體(Function.prototype.call).apply(function(a){return a;}, [0,4,3]);// func.apply(context, args)可以轉化為context.func(...args)(function(a){return a;}).call(0, 4, 3);// 所以結果很明顯,輸出4作用:用來自定義對象中的操作。
let p = new Proxy(target, handler)
target 代表需要添加代理的對象,handler 用來自定義對象中的操作,比如可以用來自定義 set 或者 get 函數。
且看一個的小栗子:
// onChange 即要進行的監聽操作var watch = (object, onChange) => { const handler = { // 如果屬性對應的值為對象,則返回一個新的Proxy對象 get(target, property, receiver) { try { return new Proxy(target[property], handler); } catch (err) { return Reflect.get(target, property, receiver); } }, // 定義或修改對象屬性 defineProperty(target, property, descriptor) { onChange('define',property); return Reflect.defineProperty(target, property, descriptor); }, // 刪除對象屬性 deleteProperty(target, property) { onChange('delete',property); return Reflect.deleteProperty(target, property); } }; return new Proxy(object, handler);};// 測試對象var obj = { name: 'bjw', age: 22, child: [1, 2, 3]}// 對象代理var p = watch(obj1, (type, property) => { console.log(`類型:${type}, 修改的屬性:${property}`)});p.name = 'qwe' 類型:define, 修改的屬性:name "qwe"p.child Proxy {0: 1, 1: 2, 2: 3, length: 3} p.child.push(4) 類型:define, 修改的屬性:3 類型:define, 修改的屬性:length 4p.child.length = 2 類型:define, 修改的屬性:length 2p.child Proxy {0: 1, 1: 2, length: 2}
新聞熱點
疑難解答
圖片精選