首頁  >  文章  >  web前端  >  js中的內部屬性與delete操作符介紹_javascript技巧

js中的內部屬性與delete操作符介紹_javascript技巧

WBOY
WBOY原創
2016-05-16 15:46:04912瀏覽

Configurableを説明する前に、まず面接の質問を見てみましょう:

a = 1;
console.log( window.a ); // 1
console.log( delete window.a ); // true
console.log( window.a ); // undefined

var b = 2;
console.log( window.b ); // 2
console.log( delete window.b ); // false
console.log( window.b ); // 2

上記の質問から、2 つの違いがわかります。変数が var を使用して宣言されていない場合、その変数は delete キーワードを使用して削除できます。変数が var を使用して宣言された場合、値は再度取得されると未定義になります。 delete を使用して削除することはできず、取得しても値は 2 のままです。

1. 演算子を削除します

delete を使用して変数または属性を削除すると、削除が成功した場合は true が返され、そうでない場合は false が返されます。上記の例のように、delete で変数 a を削除できない場合は false が返され、delete で変数 b を正常に削除できた場合は true が返されます。

上記の 2 つの状況に加えて、delete で削除できる一般的に使用される変数と、削除できない変数が他にもあります。 delete がそのような結果を生成する理由については心配しないでください。ここでは、その戻り値だけを見てみましょう:

削除配列内の要素を削除します:

// 使用for~in是循环不到的,直接忽略到该元素
// 使用for()可以得到该元素,但是值是undefined
var arr = [1, 2, 3, 4];
console.log( arr );     	// [1, 2, 3, 4]
console.log( delete arr[2] );	// true,删除成功
console.log( arr );      	// [1, 2, undefined, 4]

関数型変数の削除:

// chrome 不能删除;火狐可以删除
function func(){
}
console.log( func );
console.log( delete func );
console.log( func );

取得した仮パラメータの数である function.length を削除します:

function func1(a, b){
}
console.log( func1.length );   	// 2
console.log( delete func1.length );	// true,删除成功
console.log( func1.length );   	// 0

よく使用される変数を削除します:

console.log( delete NaN );  	// false,删除失败
console.log( delete undefined );// false
console.log( delete Infinity );	// false
console.log( delete null );  	// true,删除成功

プロトタイプの属性を削除するのではなく、プロトタイプを削除します:

function Person(){
}
Person.prototype.name = "蚊子";
console.log( delete Person.prototype );	// false,无法删除
console.log( delete Object.prototype );	// false

配列や文字列の長さを削除する場合:

var arr = [1, 2, 3, 4];
console.log( arr.length );    	// 4
console.log( delete arr.length ); 	// false,删除失败
console.log( arr.length );    	// 4

var str = 'abcdefg';
console.log( str.length );    	// 7
console.log( delete str.length ); 	// false,删除失败
console.log( str.length );    	// 7

obj の属性を削除する場合:

var obj = {name:'wenzi', age:25};
console.log( obj.name );   	// wenzi
console.log( delete obj.name );	// true,删除成功
console.log( obj.name );   	// undefined
console.log( obj );      	// { age:25 }

インスタンス オブジェクトの属性を削除する場合、次の出力からわかるように、delete を使用して属性を削除すると、インスタンス オブジェクト自体の属性のみが削除され、プロトタイプの属性は削除できないことがわかります。再度削除しても削除されません。プロトタイプの属性または属性のメソッドを削除する場合は、delete Person.prototype.name:

のみを削除できます。
function Person(){
  this.name = 'wenzi';
}
Person.prototype.name = '蚊子';
var student = new Person();
console.log( student.name );    // wenzi
console.log( delete student.name ); // true,删除成功
console.log( student.name );    // 蚊子
console.log( delete student.name ); // true
console.log( student.name );    // 蚊子
console.log( delete Person.prototype.name );// true,删除成功
console.log( student.name );    // undefined

2. js の内部プロパティ

上記の例では、一部の変数または属性は正常に削除できますが、他の変数または属性は削除できないということになります。

ECMA-262 第 5 版は、JS オブジェクト プロパティ (JS エンジンで使用され、外部から直接アクセスできない) の特性を定義します。 ECMAScript には、データ プロパティとアクセサー プロパティの 2 種類のプロパティがあります。

2.1 データ属性

データ属性は、値の読み取りまたは書き込みが可能なデータ値を含む場所を指します。この属性には、その動作を説明する 4 つのプロパティがあります。

    [[configurable]]: delete 演算子を使用して削除および再定義できるかどうか、またはアクセサー属性として変更できるかどうかを示します。デフォルトは true です。
  • [[Enumberable]]: for-in ループを通じて属性を返すことができるかどうかを示します。デフォルトは true;
  • [[Writable]]: 属性の値を変更できるかどうかを示します。デフォルトは true;
  • [[Value]]: この属性のデータ値が含まれます。この値は読み取り/書き込み可能です。デフォルトは未定義です。たとえば、name 属性は上記のインスタンス オブジェクト Person で定義されており、その値は 'wenzi' になります。この値は
  • で変更されます。
オブジェクト プロパティのデフォルト特性 (デフォルトは true) を変更するには、Object.defineProperty() メソッドを呼び出すことができます。このメソッドは、プロパティが配置されているオブジェクト、プロパティ名、記述子オブジェクトの 3 つのパラメータを受け取ります (構成可能、番号付け可能、書き込み可能、​​値、1 つ以上の値を設定できる必要があります)。

は次のとおりです:

var person = {};
Object.defineProperty(person, 'name', {
  configurable: false,	// 不可删除,且不能修改为访问器属性
  writable: false,		// 不可修改
  value: 'wenzi'			// name的值为wenzi
});
console.log( person.name);			// wenzi
console.log( delete person.name );	// false,无法删除
person.name = 'lily';
console.log( person.name );			// wenzi
person.name の値は削除もリセットも有効ではないことがわかります。これは、defineProperty 関数を呼び出すとオブジェクトのプロパティの特性が変更されるためです。configurable が false に設定されると、defineProperty が変更できることに注意してください。 true に変更するためには使用されなくなりました (実行すると、次のエラーが報告されます: Uncaught TypeError: Cannot redefine property: name);

2.2 アクセサーのプロパティ

これには主にゲッター関数とセッター関数のペアが含まれています。アクセサー属性を読み取るときはゲッターが呼び出され、有効な値が返されます。アクセサー属性が書き込まれるときは、セッターが呼び出され、新しい値が書き込まれます。属性には次の 4 つの特徴があります:

    [[Configurable]]: 削除演算子を使用して属性を削除および再定義できるかどうか。
  • [[Numberable]]: この属性が for-in ループで見つかるかどうか
  • [[Get]]: プロパティの読み取り時に自動的に呼び出されます、デフォルト: unknown;
  • [[Set]]: 属性を書き込むときに自動的に呼び出されます、デフォルト: 未定義;
  • アクセサー プロパティは直接定義できません。次のように、defineProperty() を使用して定義する必要があります。

var person = {
  _age: 18
};
Object.defineProperty(person, 'isAdult', {
	Configurable : false,
  get: function () {
    if (this._age >= 18) {
      return true;
    } else {
      return false;
    }
  }
});
console.log( person.isAdult ); // true
ただし、Object.defineProperty() メソッドでプロパティを設定する場合、アクセサー プロパティ (set および get) とデータ プロパティ (書き込み可能または値) を同時に宣言することはできません。これは、プロパティに書き込み可能属性または値属性セットがある場合、このプロパティは get または set を宣言できず、その逆も同様であることを意味します。

次のように定義すると、アクセサー プロパティとデータ プロパティが同時に存在します:

上面的代码看起来貌似是没有什么问题,但是真正执行时会报错,报错如下:

Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value

对于数据属性,可以取得:configurable,enumberable,writable和value;

对于访问器属性,可以取得:configurable,enumberable,get和set。

由此我们可知:一个变量或属性是否可以被删除,是由其内部属性Configurable进行控制的,若Configurable为true,则该变量或属性可以被删除,否则不能被删除。

可是我们应该怎么获取这个Configurable值呢,总不能用delete试试能不能删除吧。有办法滴!!

2.3 获取内部属性

ES5为我们提供了Object.getOwnPropertyDescriptor(object, property)来获取内部属性。

如:

var person = {name:'wenzi'};
var desp = Object.getOwnPropertyDescriptor(person, 'name'); // person中的name属性
console.log( desp );	// {value: "wenzi", writable: true, enumerable: true, configurable: true}

通过Object.getOwnPropertyDescriptor(object, property)我们能够获取到4个内部属性,configurable控制着变量或属性是否可被删除。这个例子中,person.name的configurable是true,则说明是可以被删除的:

console.log( person.name );			// wenzi
console.log( delete person.name );	// true,删除成功
console.log( person.name );			// undefined

我们再回到最开始的那个面试题:

a = 1;
var desp = Object.getOwnPropertyDescriptor(window, 'a');
console.log( desp.configurable ); 	// true,可以删除

var b = 2;
var desp = Object.getOwnPropertyDescriptor(window, 'b');
console.log( desp.configurable ); 	// false,不能删除

跟我们使用delete操作删除变量时产生的结果是一样的。

3. 总结

别看一个简简单单的delete操作,里面其实包含了很多的原理!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn