文档章节

js中的内部属性与delete操作符

wenzichel
 wenzichel
发布于 2015/08/03 23:44
字数 1877
阅读 18
收藏 0

本文正式地址:http://www.xiabingbao.com/javascript/2015/08/03/javascript-delete-configurable

在讲解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

从上面的这道题可以看出两个的区别:在没有使用var声明变量时,使用delete关键词是可以进行删除的,再次获取时值就是undefined了;在使用var声明的变量,使用delete是不能删除的,再获取时值依然是2。

###1. delete操作符
使用delete删除变量或属性时,删除成功返回true,否则返回false。如上面的例子中,delete无法删除变量a时,则返回false;而delete能成功删除变量b,则返回true。

除了上述的两种情况,还有其他的各种常用变量也有能被delete删除的,也有不能被删除的。我们先不管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]

删除function类型的变量:

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

删除function.length,该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,删除成功

删除prototype,而不是删除prototype上的属性:

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

删除数组和字符串的length时:

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删除属性时,删除的仅仅是实例对象本身的属性,而不能删除prototype上的属性,即使再删一次也是删除掉不的;若要删除prototype上的属性的属性或方法,只能是: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.1 数据属性
数据属性指包含一个数据值的位置,可在该位置读取或写入值,该属性有4个供述其行为的特性:

  • [[configurable]]:表示能否使用delete操作符删除从而重新定义,或能否修改为访问器属性。默认为true;
  • [[Enumberable]]:表示是否可通过for-in循环返回属性。默认true;
  • [[Writable]]:表示是否可修改属性的值。默认true;
  • [[Value]]:包含该属性的数据值。读取/写入都是该值。默认为undefined;如上面实例对象Person中定义了name属性,其值为’wenzi’,对该值的修改都反正在这个位置

要修改对象属性的默认特征(默认都为true),可调用Object.defineProperty()方法,它接收三个参数:属性所在对象,属性名和一个描述符对象(必须是:configurable、enumberable、writable和value,可设置一个或多个值)。

如下:

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

可以看出,delete及重置person.name的值都没有生效,这就是因为调用defineProperty函数修改了对象属性的特征;值得注意的是一旦将configurable设置为false,则无法再使用defineProperty将其修改为true(执行会报错:Uncaught TypeError: Cannot redefine property: name);

####2.2 访问器属性
它主要包括一对getter和setter函数,在读取访问器属性时,会调用getter返回有效值;写入访问器属性时,调用setter,写入新值;该属性有以下4个特征:

  • [[Configurable]]:是否可通过delete操作符删除重新定义属性;
  • [[Numberable]]:是否可通过for-in循环查找该属性;
  • [[Get]]:读取属性时自动调用,默认:undefined;
  • [[Set]]:写入属性时自动调用,默认:undefined;

访问器属性不能直接定义,必须使用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)和数据属性(writable或者value)。意思就是,某个属性设置了writable或者value属性,那么这个属性就不能声明get和set了,反之亦然。

如若像下面的方式进行定义,访问器属性和数据属性同时存在:

var o = {};
Object.defineProperty(o, 'name', {
    value: 'wenzi',
    set: function(name) {
        myName = name;
    },
    get: function() {
        return myName;
    }
});

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

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操作,里面其实包含了很多的原理!

本文正式地址:http://www.xiabingbao.com/javascript/2015/08/03/javascript-delete-configurable

© 著作权归作者所有

wenzichel
粉丝 0
博文 5
码字总数 9296
作品 0
朝阳
私信 提问
JavaScript面向对象技术(一)

看了很多JavaScript的书,但是设计到一些具体的JavaScript问题,书也解决不了问题。 这篇文章是参考<<javascript-the definitive guide,5th edition>>第7,8,9章而写成的,我也会尽量按照原书的...

oecp
2011/04/20
180
2
Javascript的变量与delete操作符

Javascript的变量 实际上Javascript中,变量 = 对象属性,这是因为 Javascript 在执行脚本之前 会创建一个Global对象,所有的全局变量都是这个Global对象的属性, 执行函数时也会创建一个Act...

黄平俊
2009/11/04
735
0
深入详解javascript之delete操作符

最近重新温习JS,对delete操作符一直处于一知半解的状态,偶然发现一篇文章,对此作了非常细致深入的解释,看完有茅塞顿开的感觉,不敢独享,大致翻译如下。 原文地址:http://perfectionki...

lizuochao
2011/07/29
246
0
45个有用的JavaScript技巧,窍门和最佳实践

1. 首次为变量赋值时务必使用var关键字 变量没有声明而直接赋值得话,默认会作为一个新的全局变量,要尽量避免使用全局变量。 2. 使用===取代== ==和!=操作符会在需要的情况下自动转换数据类...

kovlento
05/08
0
0
JavaScript编程注意事项、技巧大全

收藏自 JavaScript奇技淫巧45招 JavaScript是一个绝冠全球的编程语言,可用于Web开发、移动应用开发(PhoneGap、Appcelerator)、服务器端开发(Node.js和Wakanda)等等。JavaScript还是很多...

kidsamong
09/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【2019个推开发者节】航母级APP都在用的SDK现在全部免费,35岁老程序员表示第一次见!

1024程序员节来了 双11近了 各路满减、折扣、领券、秒杀、集赞 营销玩法猛于虎,一看优惠两毛五 日常拼命赶“需求” 修“Bug”的开发者们 想找个好用又不贵的工具太难了 亲爱的开发者们,不要...

个推
31分钟前
9
0
Ceph对可用存储空间的校验与控制

Ceph一共使用了四个配置对可用存储空间进行校验并实施控制,如下: mon_osd_full_ratio:集群中的任一OSD空间使用率大于等于此数值时,集群将被标记为Full,此时集群将停止接受来自客户端的写...

浪里个浪浪
32分钟前
11
0
工厂方法模式

1.定义:创建一个接口,协助创建其它对象 2.优缺点 优: a.用户只需要知道这个工厂是创建哪种对象的,不需要知道创建的过程 b.满足开闭原则(开闭原则:对扩展开放,对修改关闭,即增加类可以...

wen123
34分钟前
6
0
Bootstrap Table -detailView和detailFilter的使用

查看表格 detailFilter 属性:data-detail-filter Type:Function Default:function(index,row){ return true} detailView 属性:data-detail-view Type:Boolean Default:false <table id="ta......

tianyawhl
38分钟前
4
0
场效应管的注意事项

  (1)为了安全使用场效应管,在线路的设计中不能超过管的耗散功率,最大漏源电压、最大栅源电压和最大电流等参数的极限值。   (2)各类型场效应管在使用时,都要严格按要求的偏置接入...

仙溪
41分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部