本文详细解析JavaScript中delete运算符的用法。涵盖其基本语法、返回值规则(返回true或false),以及不可删除的情况,如var/function声明的变量和原型链属性。重点探讨delete在数组中的应用,指出其不会改变数组长度且元素变为undefined,对比直接赋undefined的区别,并提供eval环境下的特例说明。
delete运算符语法与基本用法
使用delete运算符时,其后跟随的表达式必须是一个属性的引用。例如:
var o = {a:1};
delete o.a; //此处o.a是对象o的属性a的引用
只有在with语句的作用域内,才能直接使用单独的属性名进行删除操作。
代码如下:
with(o){
delete a;
} 二、delete的返回值
delete运算符的返回值规则
delete是一个普通运算符,执行后会返回true或false。其判断规则为:如果被删除的属性存在且该属性不可配置(即不能被删除),则返回false;其他情况(包括属性不存在)均返回true。因此,返回值true并不完全等同于删除操作成功,它仅表示该属性当前没有不可配置的标记或根本不存在。
代码如下:
var o = {a:1};
delete o.a; //返回true
var b = 2;
delete b;//返回false,ECMA规范规定:使用var和function语句声明的变量和函数无法通过delete删除 三、哪些情况下不允许delete
不可删除的情况与原型链处理
前文提到的由var和function声明的变量无法被删除,但通过隐式方式声明的全局变量(即未使用var声明直接赋值)是可以被删除的。
代码如下:
function c(){return 12;}
delete c;//返回false
d = function(){return 12;}
delete d;//返回true 无法使用delete删除从原型链上继承的属性,但可以直接删除原型对象上的属性。
代码如下:
function Foo(){}
Foo.prototype.bar = 42;
var foo = new Foo();
delete foo.bar; // 返回true,但并没有起作用
alert(foo.bar); // alerts 42, 属性是继承的
delete Foo.prototype.bar; // 在原型上删除属性bar
alert(foo.bar); // alerts "undefined", 属性已经不存在,无法被继承 四、特例
eval环境下的删除特例
代码如下:
eval执行的代码中,如果通过var或function声明了变量,这些变量在eval作用域外是可以被删除的。
eval("var a=1");
delete a;
alert(a); //报未定义错误 如果变量声明位于eval执行代码内部的闭包中,则该变量无法被外部delete操作删除。
eval("(function(){var a=1;delete a; return a;})()");//1
五、delete 数组元素
delete操作对数组元素的影响
从数组中使用delete删除元素,并不会改变数组的length属性。
代码如下:
var arr = ['yuyin','suhuan','baby'];
delete arr[0];
alert(arr.length);//alert 3 被delete操作处理的键值虽然已从数组中移除,不再属于数组的常规元素,但仍可通过索引访问,其值为undefined。
代码如下:
var arr = ['yuyin','suhuan','baby'];
delete arr[0];
0 in arr; // false
alert(arr[0]);//undefined
arr[0] === undefined;//true 对比直接将键值赋值为undefined的情况
代码如下:
var arr = ['yuyin','suhuan','baby'];
arr[0] = undefined;
0 in arr; // true
alert(arr[0]);//undefined
arr[0] === undefined;//true 由此可见,delete操作实质上是将键值从数组对象中移除,但数组本身作为对象的结构保持不变。若需保留键位但清空值,应直接赋值为undefined。