你认为每个程序员都应该知道JavaScript的哪些“隐藏特性”?

在看到以下问题的优质答案后,我认为是时候向JavaScript请求它了。

HTML的隐藏特性 CSS的隐藏特性 PHP的隐藏特性 ASP的隐藏特性。网 c#的隐藏特性 Java的隐藏特性 Python的隐藏特性

尽管JavaScript可以说是目前最重要的客户端语言(问问谷歌就知道了),但令人惊讶的是,大多数web开发人员很少意识到它的强大。


当前回答

大多数时候可以使用对象而不是开关。

function getInnerText(o){
    return o === null? null : {
        string: o,
        array: o.map(getInnerText).join(""),
        object:getInnerText(o["childNodes"])
    }[typeis(o)];
}

更新:如果你担心提前评估的情况是低效的(为什么你在程序设计的早期就担心效率??),那么你可以这样做:

function getInnerText(o){
    return o === null? null : {
        string: function() { return o;},
        array: function() { return o.map(getInnerText).join(""); },
        object: function () { return getInnerText(o["childNodes"]; ) }
    }[typeis(o)]();
}

这比输入(或读取)开关或对象更麻烦,但它保留了使用对象而不是开关的好处,详情见下面的评论部分。这种风格还使它在足够成熟后更直接地旋转成一个适当的“类”。

update2:带有ES的建议语法扩展。接下来,这变成了

let getInnerText = o -> ({
    string: o -> o,
    array: o -> o.map(getInnerText).join(""),
    object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);

其他回答

JavaScript中最快的循环是while(i——)循环。在所有浏览器中。 所以如果循环元素的处理顺序不是那么重要,你应该使用while(i——)形式:

var names = new Array(1024), i = names.length;
while(i--)
  names[i] = "John" + i;

此外,如果你必须继续使用for()循环,请记住始终缓存.length属性:

var birds = new Array(1024); 
for(var i = 0, j = birds.length; i < j; i++)
  birds[i].fly();

要连接大字符串使用数组(它更快):

var largeString = new Array(1024), i = largeString.length;
while(i--) {
  // It's faster than for() loop with largeString.push(), obviously :)
  largeString[i] = i.toString(16);
}

largeString = largeString.join("");

它比循环中的largeString += "something"快得多。

大多数时候可以使用对象而不是开关。

function getInnerText(o){
    return o === null? null : {
        string: o,
        array: o.map(getInnerText).join(""),
        object:getInnerText(o["childNodes"])
    }[typeis(o)];
}

更新:如果你担心提前评估的情况是低效的(为什么你在程序设计的早期就担心效率??),那么你可以这样做:

function getInnerText(o){
    return o === null? null : {
        string: function() { return o;},
        array: function() { return o.map(getInnerText).join(""); },
        object: function () { return getInnerText(o["childNodes"]; ) }
    }[typeis(o)]();
}

这比输入(或读取)开关或对象更麻烦,但它保留了使用对象而不是开关的好处,详情见下面的评论部分。这种风格还使它在足够成熟后更直接地旋转成一个适当的“类”。

update2:带有ES的建议语法扩展。接下来,这变成了

let getInnerText = o -> ({
    string: o -> o,
    array: o -> o.map(getInnerText).join(""),
    object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);

我知道我迟到了,但我只是无法相信+运算符的有用性除了“将任何东西转换为数字”之外没有被提及。也许这就是隐藏得有多好?

// Quick hex to dec conversion:
+"0xFF";              // -> 255

// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();

// Safer parsing than parseFloat()/parseInt()
parseInt("1,000");    // -> 1, not 1000
+"1,000";             // -> NaN, much better for testing user input
parseInt("010");      // -> 8, because of the octal literal prefix
+"010";               // -> 10, `Number()` doesn't parse octal literals 

// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null;                // -> 0;

// Boolean to integer
+true;                // -> 1;
+false;               // -> 0;

// Other useful tidbits:
+"1e10";              // -> 10000000000
+"1e-4";              // -> 0.0001
+"-12";               // -> -12

当然,你也可以用Number()来代替,但是+运算符要漂亮得多!

您还可以通过重写原型的valueOf()方法为对象定义一个数值返回值。在该对象上执行的任何数字转换都不会导致NaN,而是valueOf()方法的返回值:

var rnd = {
    "valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd;               // -> 442;
+rnd;               // -> 727;
+rnd;               // -> 718;

确保在遍历对象属性时使用hasOwnProperty方法:

for (p in anObject) {
    if (anObject.hasOwnProperty(p)) {
        //Do stuff with p here
    }
}

这样做是为了只访问object的直接属性,而不使用原型链下面的属性。

JavaScript没有块作用域(但它有闭包,所以让我们称它为偶数?)

var x = 1;
{
   var x = 2;
}
alert(x); // outputs 2