微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

在讲解Configurable之前,我们首先来看一道面试题:

rush:js;"> 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。

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

除了上述的两种情况,还有其他的各种常用变量也有能被delete删除的,也有不能被删除的。我们先不管

delete

这些变量时,为什么会产生这样的结果,这里只看他的返回值:

删除delete数组中其中的一个元素:

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

删除function类型的变量:

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

删除function.length,该length是获取形参的个数:

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

删除常用变量:

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

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

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

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

rush:js;"> var arr = [1,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中的属性时:

rush:js;"> 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

rush:js;"> 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

属性

在上面的例子中,有的变量或属性能删除成功,而有的变量或属性则无法进行删除,那是什么决定这个变量或属性能不能被删除呢。

ECMA-262第5版定义了JS对象属性中特征(用于JS引擎,外部无法直接访问)。ECMAScript中有两种属性:数据属性和访问器属性

属性

数据属性指包含一个数据值的位置,可在该位置读取或写入值,该属性有4个供述其行为的特性:

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

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

如下:

rush:js;"> 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);

属性

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

访问器属性不能直接定义,必须使用defineproperty()来定义,如下:

= 18) { return true; } else { return false; } } }); console.log( person.isAdult ); // true

不过还是有一点需要额外注意一下,Object.defineproperty()方法设置属性时,不能同时声明访问器属性(set和get)和数据属性(writable或者value)。意思就是,某个属性设置了writable或者value属性,那么这个属性就不能声明get和set了,反之亦然。

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

rush:js;"> var o = {}; Object.defineProperty(o,{ 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,get和set。

由此我们可知:

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

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

获取内部属性

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

如:

rush:js;"> 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,则说明是可以被删除的:

rush:js;"> console.log( person.name ); // wenzi console.log( delete person.name ); // true,删除成功 console.log( person.name ); // undefined

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

rush:js;"> 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操作删除变量时产生的结果是一样的。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是深拷贝与浅拷贝?深拷贝与浅拷贝是js中处理对象或数据复制操作的两种方式。‌在聊深浅拷贝之前咱得了解一下js中的两种数据类型:
前言 今天复习了一些前端算法题,写到一两道比较有意思的题:重建二叉树、反向输出链表每个节点 题目 重建二叉树: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8} 和中序遍历序列 {
最近在看回JavaScript的面试题,this 指向问题是入坑前端必须了解的知识点,现在迎来了ES6+的时代,因为箭头函数的出现,所以感觉有必要对 this 问题梳理一下,所以刚好总结一下JavaScript中this指向的问题。
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高