为了账号安全,请及时绑定邮箱和手机立即绑定

如何从JavaScript对象中删除属性?

如何从JavaScript对象中删除属性?

偶然的你 2019-05-25 16:04:25
如何从JavaScript对象中删除属性?假设我创建一个对象如下:var myObject = {     "ircEvent": "PRIVMSG",     "method": "newURI",     "regex": "^http://.*"};删除属性的最佳方法是什么regex,最终得到myObject如下新内容?var myObject = {     "ircEvent": "PRIVMSG",     "method": "newURI"};
查看完整描述

4 回答

?
www说

TA贡献1775条经验 获得超8个赞

var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

    

delete myObject.regex;


console.log ( myObject.regex); // logs: undefined


查看完整回答
反对 回复 2019-05-25
?
缥缈止盈

TA贡献2041条经验 获得超4个赞

短版

这个问题的实际答案

正如其他人所说,你可以使用delete。


obj // {"foo": "bar"}

delete obj["foo"]

obj // {}

obj["foo"] // undefined

数组等价

不要delete从阵列。请Array.prototype.splice改用。


arr // [1,2,3,4,5]

arr.splice(3,1); // 4

arr // [1,2,3,5]

长版

JavaScript是一种OOP语言,所以一切都是对象,包括数组。因此,我认为有必要指出一个特别的警告。


在数组中,与普通的旧对象不同,使用delete垃圾形式的叶子null,在数组中创建一个“洞”。


var array = [1, 2, 3, 4];

delete array[2];

/* Expected result --> [1, 2, 4]

 * Actual result   --> [1, 2, null, 4]

 */

正如您所看到的,delete并不总是像人们期望的那样工作。该值被覆盖,但内存未重新分配。也就是说,array[4]没有重新安置array[3]。与之形成对比的是Array.prototype.unshift,它在数组的开头插入一个元素并将所有内容都移位(array[0]变为array[1]等)


老实说,除了设置null而不是undefined,可呈现为合法怪异-这种行为不应该是不足为奇的,因为delete是一元运算符,如typeof,就是煮到语言,不应该在乎类型的对象正在被使用,而是使用专门用于处理数组的方法Array的子类。所以没有充分的理由让一个特殊的盒子用于重新移动阵列,因为这会减少不必要的工作。回想起来,我的期望是不现实的。Objectdelete


当然,这也让我感到吃惊。因为我写这篇文章是为了证明我对“空垃圾”的讨伐:


忽略固有的危险和问题null,以及浪费的空间,如果阵列需要精确,这可能会有问题。


这是摆脱了可怕的理由nullS-- null只危险的,如果使用不当,它没有任何与“精确”。你不应该delete从数组中获得的真正原因是,留下垃圾填充和混乱的数据结构是邋and和容易出错的。


接下来是一个设计得非常冗长的场景,所以如果你愿意,可以跳到“解决方案”这一部分。我离开这一部分的唯一原因是,我认为有些人可能认为这很有趣,而且我不想成为那个发布“有趣”答案然后从中删除所有“搞笑”的“那个人”。 。


......我知道,这很愚蠢。


设计和冗长的PDP-11场景

例如,假设您正在创建一个webapp,它使用JSON序列化来存储用于字符串中“tabs”的数组(在本例中localStorage)。我们还要说代码在绘制到屏幕时使用数组成员的数字索引来“标题”它们。你为什么这样做而不仅仅是存储“标题”?因为...... 原因。


好的,我们只是说你正在努力节省内存,应运行这台运行一台1960年代运行UNIX的PDP-11小型机的用户,并编写了自己的基于Elinks,符合JavaScript标准的线路打印机友好型浏览器因为X11是不可能的。


除了越来越愚蠢的边缘情况之外,delete在所述数组上使用将导致null污染数组,并可能在以后导致应用程序中的错误。如果你检查null,它会直接跳过数字,导致标签被渲染出来[1] [2] [4] [5] ...。


if (array[index] == null)

    continue;

else

    title = (index + 1).toString();

/* 0 -> "1"

 * 1 -> "2"

 * 2 -> (nothing)

 * 3 -> "4"

 */

是的,这绝对不是你想要的。


现在,您可以保留第二个迭代器,例如j,仅在从数组中读取有效值时才递增。但这并不能完全解决null问题,你仍然需要取悦那个troll PDP-11用户。唉,他的计算机没有足够的内存来容纳最后一个整数(不要问他是如何设法处理可变宽度数组的......)。


所以,他给你发了一封愤怒的电子邮件:


Hey, your webapp broke my browser! I checked my localStorage database after your stupid code made my browser segfault, and this is what I found:


>"tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]"


After clearing my precious data, it segfaulted again, and I did a backtrace, and what do I find? WHAT DO I FIND!? YOU USE TOO MANY VARIABLES!


>var i = index;

>var j = 1;


Grr, I am angry now.

-Troll Davidson

现在,你的智慧结束了。这家伙一直抱怨你的应用程序不停,你想告诉他闭嘴,去买一台更好的电脑。


解决方案: Array.prototype.splice

幸运的是,数组确实有一种删除索引和重新分配内存的专门方法:Array.prototype.splice()。你可以写这样的东西:


Array.prototype.remove = function(index){

  this.splice(index,1);

}

...

array = [1, 2, 3, 4];

array.remove(2);

// Result -> [1, 2, 4]

就这样,你很高兴PDP-11先生。万岁!(我还是告诉他,不过......)


Array.prototype.splice vs Array.prototype.slice

我觉得指出这两个同名的函数之间的区别非常重要,因为它们都非常有用。


Array.prototype.splice(start,n)

.splice()改变数组,并返回删除的索引。从索引开始切割数组start,并n切出元素。如果未指定n,则将整个数组start切出(n = array.length - start)。


let a = [5,4,3,2,1];

let chunk = a.splice(2,2);


// a     [5,4,3,2,1]

// start  0 1 2 - -

// n      - - 1 2 -


chunk; // [3,2]

a;     // [5,4,1]

Array.prototype.slice(开始,结束)

.slice()是非破坏性的,并返回从含有指示索引的新的数组start,以end。如果end未指定,则行为与.splice()(end = array.length)相同。这个行为有点棘手,因为由于某种原因,end索引从1而不是0.我不知道为什么会这样做,但事实就是如此。另外,如果end <= start,结果是一个空数组。


let a = [5,4,3,2,1];

let chunks = [

    a.slice(2,0),

    a.slice(2,2),

    a.slice(2,3),

    a.slice(2,5) ];


// a             [5,4,3,2,1]

// start          0 1 2 - -

// end, for...    - - - - -

//   chunks[0]  0 - - - - -   

//   chunks[1]    1 2 - - -

//   chunks[2]    1 2 3 - -

//   chunks[3]    1 2 3 4 5


chunks; // [ [], [], [3], [3,2,1] ]

a;      // [5,4,3,2,1]

这实际上不是正在发生的事情,但更容易想到这种方式。根据MDN,这是实际发生的事情:


// a             [5,4,3,2,1]

// start          0 1 2 - - -

// end, for...    - - - - - -

//   chunks[0]    0 - - - - -

//   chunks[1]    0 1 2 - - -

//   chunks[2]    0 1(2)3 - -

//   chunks[3]    0 1(2 3 4)5

指定的索引end只是从切片中排除。带括号的索引表示切片的内容。无论哪种方式,行为都不直观,并且它必然导致其公平分享一个一个错误,因此您可能会发现使包装函数更接近地模拟以下行为是有用的.splice():


function ez_slice(array, start = 0, n = null){

    if(!Array.isArray(array) || !is_number(start))

        return null;


    if(is_number(n))

        return array.slice(start, start + n);


    if(n === null)

        return array.slice(start);


    return null;

}


ez_slice([5,4,3,2,1], 2, 1) // [3]

ez_slice([5,4,3,2,1], 2)    // [3,2,1]


/* Fun fact: isNaN is unreliable.

 * [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(isNaN)

 * [NaN, {}, undefined, "Hi"]

 *

 * What we want is...

 *

 * [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(is_nan)

 * [NaN]

 */

function is_nan(num){

    return typeof num === "number"

        && num !== num;

}


function is_number(num){

    return !is_nan(num)

        && typeof num === "number"

        && isFinite(num);

}

请注意,包装函数的设计对类型非常严格,null如果有任何关闭则会返回。这包括输入一个字符串"3"。程序员需要勤勉地研究他的类型。这是为了鼓励良好的编程实践。


有关的更新 is_array()

这是关于这个(现在删除)的片段:


function is_array(array){

    return array !== null

        && typeof array === "object"

        && typeof array.length !== "undefined"

        && array.__proto__ === Array.prototype;

}

事实证明,实际上有一种内置的方法来判断一个数组是否真的是一个数组,这就是Array.isArray()在ECMAScript 5(2009年12月)中引入的。我找到了这个,同时查看是否有一个问题询问是否从对象告诉数组,看看是否有比我更好的解决方案,或者如果没有,则添加我的。因此,如果您使用的是早于ECMA 5的JavaScript版本,那么就是您的polyfill。但是,我强烈建议不要使用我的is_array()功能,因为继续支持旧版本的JavaScript意味着继续支持实现它们的旧浏览器,这意味着鼓励使用不安全的软件并使用户面临恶意软件的风险。所以,请使用Array.isArray()。使用let和const。使用添加到该语言的新功能。不要使用供应商前缀。从您的网站删除 IE polyfill废话。删除那个XHTML <!CDATA[[...废话 - 我们在2014年转移到HTML5。每个人都越早撤回对那些旧/深奥浏览器的支持,浏览器供应商越早实际遵循Web标准并采用新技术,我们越早能够转向更安全的网络。


查看完整回答
反对 回复 2019-05-25
  • 4 回答
  • 0 关注
  • 2245 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信