淺談var和delete

好久好久之前,有我的說:我如今寫個var,腦海中都會浮現一大堆……,不知所云……數組

變量聲明

JavaScript6種變量聲明方式中(ES5:var function ES6: let const import class),var能夠顯示的聲明變量,併爲變量初始化值(可選),也能夠隱式聲明。瀏覽器

刪除變量

delete能夠用來刪除對象的屬性,若是:bash

  • delete一個用var聲明的變量
  • delete一個沒有用var聲明的變量
  • 若是加上'use strict' 會如何?

請把下面兩段分別放到控制檯執行一下函數

var a = 100;b = 200;
delete a;
delete b;
console.log(a);
console.log(b);
複製代碼

若是加個use strict,又會如何?ui

'use strict'
var a = 100;b = 200;
delete a;
delete b;
console.log(a);
console.log(b);
複製代碼

關於var

語法

var varname1 [= value1] [, varname2 [= value2] ... [, varnameN [= valueN]]];this

描述
  • var聲明的變量存在聲明提高,JavaScript引擎會在執行代碼以前將當前的變量加入到當前執行環境(call stack) 的詞法環境中,也就是hosting,變量聲明提高

  • 變量能夠沒有初始值,會保存一個特殊的值 undefined
  • 變量能夠重複定義,且能夠修改值
  • 變量聲明語句從自動提高到所在做用域的頂端
  • 函數內重複定義對函數外無影響(局部變量)
  • 函數內從新賦值對函數外有影響
  • 將未聲明的變量賦值(隱式聲明),會隱式的將該變量建立爲全局變量(我的理解爲語言缺陷,否則就不會有 use strict了)
  • 對象上新增的屬性,默認configurable爲true
var a = {}
Object.getOwnPropertyDescriptor(window,'a')
{value: {…}, writable: true, enumerable: true, configurable: false}
a.b = 1
Object.getOwnPropertyDescriptor(a,'b')
{value: 1, writable: true, enumerable: true, configurable: true}
複製代碼
  • 使用var聲明的變量,默認configurable爲false
var a = 1;
Object.getOwnPropertyDescriptor(window,'a')
{value: 1, writable: true, enumerable: true, configurable: false}
複製代碼

關於隱式聲明的例子spa

var x = 0;  // x is declared global, then assigned a value of 0

console.log(typeof z); // undefined, since z doesn't exist yet function a() { // when a is called, var y = 2; // y is declared local to function a, then assigned a value of 2 console.log(x, y); // 0 2 function b() { // when b is called x = 3; // assigns 3 to existing global x, doesn't create a new global var
    y = 4;  // assigns 4 to existing outer y, doesn't create a new global var z = 5; // creates a new global variable z and assigns a value of 5. } // (Throws a ReferenceError in strict mode.) b(); // calling b creates z as a global variable console.log(x, y, z); // 3 4 5 } a(); // calling a also calls b console.log(x, z); // 3 5 console.log(typeof y); // undefined as y is local to function a 複製代碼

關於delete

語法
delete object.property
delete object['property']
複製代碼
返回值

非嚴格模式下返回true,除了遇到configurable爲false和不能刪除的狀況prototype

說明
  • delete和內存管理無關,內存管理是經過判斷引用標記來完成的
  • 若是在對象的原型鏈上存在同名屬性,那麼在刪除以後,對象將使用原型鏈中的屬性(換句話說,刪除只對本身的屬性有影響)。
  • 不能從全局做用域或函數做用域中刪除用var聲明的任何屬性。(由於使用var聲明的)
  • delete不能刪除全局函數, 能夠刪除對象中的函數
  • 使用const和let聲明的任何變量都不能經過delete刪除
  • 沒法刪除不可配置的屬性。包括內置對象(如Math、Array、Object)的屬性,以及使用Object. defineproperty()等方法建立的不可配置的屬性。
  • 嚴格模式和非嚴格模式的區別
    • 非嚴格模式,delete刪除configurable爲false和不能刪除的返回false
    • 嚴格模式,delete刪除configurable爲false和不能刪除的直接報錯

非嚴格模式code

function Employee() { 
  delete salary;
  var salary;
}
Employee();
複製代碼

嚴格模式刪除函數、configurable爲false的都會報錯cdn

"use strict";
function Employee() {
  delete salary;  // SyntaxError 報錯
  var salary;        
}
// Similarly, any direct access to a function
// with delete will raise a SyntaxError
function DemoFunction() {
  //some code
}
delete DemoFunction; // SyntaxError
複製代碼

一些場景

// Creates the property adminName on the global scope.
adminName = 'xyz';            

// Creates the property empCount on the global scope.
// Since we are using var, this is marked as non-configurable. The same is true of let and const.
var empCount = 43;

EmployeeDetails = {
  name: 'xyz',
  age: 5,
  designation: 'Developer'
};

// adminName is a property of the global scope.
// It can be deleted since it is created without var,
// and is therefore configurable.
delete adminName;       // returns true

// On the contrary, empCount is not configurable
// since var was used.
delete empCount;       // returns false 

// delete can be used to remove properties from objects.
delete EmployeeDetails.name; // returns true 

// Even when the property does not exist, delete returns "true".
delete EmployeeDetails.salary; // returns true 

// delete does not affect built-in static properties.
delete Math.PI; // returns false 

// EmployeeDetails is a property of the global scope.
// Since it was defined without "var", it is marked configurable.
delete EmployeeDetails;   // returns true

function f() {
  var z = 44;

  // delete doesn't affect local variable names delete z; // returns false } 複製代碼

刪除原型鏈上的屬性(注意直接刪除實例的屬性,並不會影響原型的屬性)

function Foo() {
  this.bar = 10;
}

Foo.prototype.bar = 42;

var foo = new Foo();

// foo.bar is associated with the 
// own property. 
console.log(foo.bar); // 10 

// Delete the own property within the 
// foo object. 
delete foo.bar; // returns true 

// foo.bar is still available in the 
// prototype chain. 
console.log(foo.bar); // 42 

// Delete the property on the prototype.
delete Foo.prototype.bar; // returns true 

// The "bar" property can no longer be 
// inherited from Foo since it has been 
// deleted. 
console.log(foo.bar); // undefined
複製代碼

刪除數組的元素

經過delete能夠產生 稀疏數組

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3]; // 這裏至關於把trees變成了稀疏數組,why ? 由於 數組是類對象,本質上是key-value的集合,元素個數是4個,而數組的長度是5
if (3 in trees) {
    // this is not executed
}
trees.length // 5
複製代碼

關於delete怪異的地方

固然雖然沒有違背原則,可是總以爲怪怪的

image.png

參考

相關文章
相關標籤/搜索