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

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

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

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


当前回答

在Crockford的《Javascript: The Good Parts》中也提到过:

parseInt()是危险的。如果你给它一个字符串而不告诉它正确的进制,它可能会返回意想不到的数字。例如,parseInt('010')返回8,而不是10。传递一个base给parseInt可以使它正确工作:

parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.

其他回答

生成器和迭代器(仅适用于Firefox 2+和Safari)。

function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i < 10; i++) {
  document.write(g.next() + "<br>\n");
}

The function containing the yield keyword is a generator. When you call it, its formal parameters are bound to actual arguments, but its body isn't actually evaluated. Instead, a generator-iterator is returned. Each call to the generator-iterator's next() method performs another pass through the iterative algorithm. Each step's value is the value specified by the yield keyword. Think of yield as the generator-iterator version of return, indicating the boundary between each iteration of the algorithm. Each time you call next(), the generator code resumes from the statement following the yield. In normal usage, iterator objects are "invisible"; you won't need to operate on them explicitly, but will instead use JavaScript's for...in and for each...in statements to loop naturally over the keys and/or values of objects.

var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  document.write(objectWithIterator[i] + "<br>\n");
}

函数在JavaScript中是第一类公民:

var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };

var sum = function(x,y,z) {
  return x+y+z;
};

alert( passFunAndApply(sum,3,4,5) ); // 12

函数式编程技术可以用来编写优雅的javascript。

特别是,函数可以作为参数传递,例如Array.filter()接受回调:

[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]

你也可以声明一个“private”函数,它只存在于特定函数的作用域中:

function PrintName() {
    var privateFunction = function() { return "Steve"; };
    return privateFunction();
}

闭包的禅意

其他人也提到了关闭。但令人惊讶的是,有那么多人知道闭包,使用闭包编写代码,但仍然对闭包的真正含义有错误的认识。有些人混淆了一级函数和闭包。但也有人认为它是一种静态变量。

对我来说,闭包是一种“私有”全局变量。这是一种变量,一些函数将其视为全局变量,而其他函数则看不到。现在,我知道这是在快速和松散地描述底层机制,但这就是它的感觉和行为。说明:

// Say you want three functions to share a single variable:

// Use a self-calling function to create scope:
(function(){

    var counter = 0; // this is the variable we want to share;

    // Declare global functions using function expressions:
    increment = function(){
        return ++counter;
    }
    decrement = function(){
        return --counter;
    }
    value = function(){
        return counter;
    }
})()

现在,增量、减量和值这三个函数共用一个变量counter,而不是一个实际的全局变量counter。这是闭包的真正本质:

increment();
increment();
decrement();
alert(value()); // will output 1

以上并不是闭包的真正有用的用法。事实上,我认为这样使用它是一种反模式。但是它对于理解闭包的性质是有用的。例如,大多数人在尝试做以下事情时会被发现:

for (var i=1;i<=10;i++) {
    document.getElementById('span'+i).onclick = function () {
        alert('this is span number '+i);
    }
}
// ALL spans will generate alert: this span is span number 10

这是因为他们不理解闭包的本质。他们认为他们把i的值传递给了函数,而实际上这些函数共享一个变量i,就像我之前说的,一个特殊的全局变量。

为了解决这个问题,你需要分离*闭包:

function makeClickHandler (j) {
    return function () {alert('this is span number '+j)};
}

for (var i=1;i<=10;i++) {
    document.getElementById('span'+i).onclick = makeClickHandler(i);
}
// this works because i is passed by reference 
// (or value in this case, since it is a number)
// instead of being captured by a closure

*注:我不知道这里的正确术语。

函数l (f, n) {n&&l (n - 1 f, f (n));} L(函数(循环){警报(循环);}, 5);

警报5、4、3、2、1

JavaScript的通用性-覆盖默认功能

下面是覆盖窗口的代码。使用jQuery UI的对话框小部件的警报功能。我把它作为一个jQuery插件来实现。你可以在我的博客上读到;altAlert,一个用于个性化警报消息的jQuery插件。

jQuery.altAlert = function (options)  
{  
    var defaults = {  
        title: "Alert",  
        buttons: {  
            "Ok": function()  
            {  
                jQuery(this).dialog("close");  
            }  
        }  
    };  

    jQuery.extend(defaults, options);  

    delete defaults.autoOpen;  

    window.alert = function ()  
    {  
        jQuery("<div />", {
            html: arguments[0].replace(/\n/, "<br />")
        }).dialog(defaults);  
    };  
};