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

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

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

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


当前回答

存在检查。我经常看到这样的东西

var a = [0, 1, 2];

// code that might clear the array.

if (a.length > 0) {
 // do something
}

例如,你可以这样做:

var a = [0, 1, 2];

// code that might clear the array.

if (a.length) { // if length is not equal to 0, this will be true
 // do something
}

你可以做各种各样的存在性检验,但这只是一个简单的例子

下面是一个关于如何使用默认值的示例。

function (someArgument) {
      someArgument || (someArgument = "This is the deault value");
}

这是我的意见。还有其他鸡块,但就到这里了。

其他回答

JavaScript typeof运算符用于数组或null总是返回对象值,在某些情况下可能不是程序员所期望的。

这里有一个函数,它将为这些项返回正确的值。数组识别复制自Douglas Crockford的书《JavaScript: The Good Parts》。

function typeOf (value) {
    var type = typeof value;
    if (type === 'object') {
        if (value === null) {
             type = 'null';
        } else if (typeof value.length === 'number' && 
            typeof value.splice === 'function' && 
            !value.propertyIsEnumerable('length')) {
            type = 'array';
        }
    }
    return type;
}

原型继承(由Douglas Crockford推广)彻底改变了在Javascript中思考负载的方式。

Object.beget = (function(Function){
    return function(Object){
        Function.prototype = Object;
        return new Function;
    }
})(function(){});

这是一个杀手!可惜几乎没有人使用它。

它允许你“生成”任何对象的新实例,扩展它们,同时保持一个(活的)原型继承链接到它们的其他属性。例子:

var A = {
  foo : 'greetings'
};  
var B = Object.beget(A);

alert(B.foo);     // 'greetings'

// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo);     // 'hello'

A.bar = 'world';
alert(B.bar);     // 'world'


// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo);     // 'hello'

B.bar = 'universe';
alert(A.bar);     // 'world'

闭包:

function f() { 
    var a; 
    function closureGet(){ return a; }
    function closureSet(val){ a=val;}
    return [closureGet,closureSet];
}

[closureGet,closureSet]=f(); 
closureSet(5);
alert(closureGet()); // gives 5

closureSet(15);
alert(closureGet()); // gives 15

这里的闭包并不是所谓的解构赋值([c,d] =[1,3]等价于c=1;d=3;)但事实上,在closureGet和closurereset中出现的a仍然指向同一个变量。即使在closureSet已经分配了一个新值之后!

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

// 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;

你永远不需要使用eval()来组装全局变量名。

也就是说,如果你有几个名为spec_grapes, spec_apples的全局变量(无论出于什么原因),你不需要用eval("spec_" + var)访问它们。

所有全局变量都是window[]的成员,所以你可以执行window["spec_" + var]。