這兩天在幹活的時候,遇到了這麼一個業務場景.就是後臺接口返回的數據中有不少字段是我不需要的,而我只想保留幾個我想要的數據字段,不想要整個對象賦值.
我們假設後臺返回的數據如下:
{
"code" : "200",
"msg" : "操作成功",
"data" : {
"name": "zhangsan",
"age": 12,
"job": "FE developer",
"like": "football"
},
"hasError" : false
}
按照以前的做法,管它三七二十一,全給我拿來.直接把整個對象賦值給myData
aInterface().then(res => {
this.myData = res.data.data
})
然後在模板中使用:
<div>
<ul>
<li v-for="prop in myData">
{{prop}}
</li>
</ul>
</div>
而我現在只想要 name
和 age
這兩個字段,上面的做法會將所有的屬性值全部打印出來.所以,我採用的賦值方法一般是
aInterface().then(res => {
const data = res.data.data
this.myData.name = data.name
this.myData.age = data.age
})
但是這樣的寫法就顯得有點繁瑣了,每次都要寫 this.myData
這個變量了.此時想起了以前看到過的有個叫 with
的語句,語法是這樣的:
const obj = {
name:'zhangsan',
age:12
}
console.log(obj) // {name: "zhangsan", age: 12}
obj.name = 'lisi'
obj.age = 15
console.log(obj) // {name: "lisi", age: 15}
with(obj){
name = 'wangwu'
age = 18
job = 'fe'
}
console.log(obj) // {name: "wangwu", age: 18}
obj.a = 11
這種是我們最常見的給對象裏面屬性賦值的方式,而 with
後面跟了一個表達式 obj
, 花括號裏面的語句就只需要 a = 111
這樣的賦值方式,感覺是可以少寫一點代碼了. 那麼我們可以看出,其實 with
關鍵字改變了裏面語句的作用域,在 with
代碼塊內部,變量會先被認爲是一個局部變量,如果某個變量名與表達式 obj
中的一個屬性名是一樣的,那麼這個局部變量就會指向 obj
對象中同名屬性.但假如 obj
中沒有一個屬性名是與代碼塊中的局部變量的名字是一樣的,那麼此時就會發生污染全局變量的現象.不知道小夥伴們是否注意到了,上面的代碼中,在代碼塊的最後,我加了 job = 'fe'
這樣的一句語句.但是,console 控制檯打印出來的 obj
中並沒有包含這個屬性.這就是因爲此時的 job
這個變量已經泄漏到了全局作用域中了,我們可以繼續在控制檯執行下面代碼
console.log(job === window.job) // true
會發現結果是 true
,證明此時 job
已經是全局變量了.這就是 with
的其中一個弊端,容易數據泄漏,污染全局.而 with
的另外一個缺點就是會導致性能下降.我們來運行如下代碼,然後在控制檯查看運行結果:
function test(){
console.time('test')
const obj = {
a:1
}
for(let i = 0;i < 99999; i++){
const tmp = obj.a
}
console.timeEnd('test')
}
test() // test: 1.2958984375ms
function testWith(){
console.time('testWith')
const obj = {
a:1
}
with(obj){
for(let i = 0;i < 99999; i++){
const tmp = a
}
}
console.timeEnd('testWith')
}
testWith() // testWith: 12.7939453125ms
注意:
console.time()
方法是作爲計算器的起始方法, console.timeEnd()
方法作爲計算器的結束方法 . 兩個方法配合使用,一般是用來測試一段程序執行的時長.所以,這裏兩個函數的運行結果很可能是每次都不一樣的,但是每次偏差應該都不會相差太大.由此,我們可以看出使用了 with
語句的代碼所需要的時間更長.是沒有使用with語句的好多倍.這是因爲JavaScript引擎在編譯階段就進行一些性能優化,比如在執行之前就確定了一些變量的定義位置,然後在代碼真正的執行過程中可以快速的找到標識符,而使用了 with
之後,因爲無法知道傳遞到with
中的對象是哪個,所以JavaScript引擎它也會很懵逼,然後選擇放棄,不做優化.
總結:
我們代碼中儘量不推薦使用 with
語句,並且在ES5嚴格模式中已經禁止該標籤.但假如真的很想要用它的話,那麼在 with
代碼塊的語句中,儘量使用指定對象的屬性作爲變量名,至少我們要保證儘量的不污染全局.