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

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

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

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


当前回答

正如Marius已经指出的,可以在函数中使用公共静态变量。

我通常使用它们来创建只执行一次的函数,或者缓存一些复杂的计算结果。

下面是我以前的“单例”方法的例子:

var singleton = function(){ 

  if (typeof arguments.callee.__instance__ == 'undefined') { 

    arguments.callee.__instance__ = new function(){

      //this creates a random private variable.
      //this could be a complicated calculation or DOM traversing that takes long
      //or anything that needs to be "cached"
      var rnd = Math.random();

      //just a "public" function showing the private variable value
      this.smth = function(){ alert('it is an object with a rand num=' + rnd); };

   };

  }

  return arguments.callee.__instance__;

};


var a = new singleton;
var b = new singleton;

a.smth(); 
b.smth();

如您所见,在这两种情况下构造函数都只运行一次。

For example, I used this approach back in 2004 when I had to create a modal dialog box with a gray background that covered the whole page (something like Lightbox). Internet Explorer 5.5 and 6 have the highest stacking context for <select> or <iframe> elements due to their "windowed" nature; so if the page contained select elements, the only way to cover them was to create an iframe and position it "on top" of the page. So the whole script was quite complex and a little bit slow (it used filter: expressions to set opacity for the covering iframe). The "shim" script had only one ".show()" method, which created the shim only once and cached it in the static variable :)

其他回答

我可以引用道格拉斯·克罗克福德这本好书的大部分内容 JavaScript:好的部分。

但我只给你一个,总是使用===和!==而不是==和!=

alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true

==是不可传递的。如果你使用===,它会给出false for 所有这些陈述都符合预期。

有些人会说这是品味问题,但是:

aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }

三元操作符可以被链接到Scheme的(cond…):

(cond (predicate  (action  ...))
      (predicate2 (action2 ...))
      (#t         default ))

可以写成……

predicate  ? action( ... ) :
predicate2 ? action2( ... ) :
             default;

这是非常“实用的”,因为它可以在没有副作用的情况下对代码进行分支。所以不要:

if (predicate) {
  foo = "one";
} else if (predicate2) {
  foo = "two";
} else {
  foo = "default";
}

你可以这样写:

foo = predicate  ? "one" :
      predicate2 ? "two" :
                   "default";

也适用于递归:)

生成器和迭代器(仅适用于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");
}

所有“隐藏的”特性都在Mozilla wiki上:http://developer.mozilla.org/en/JavaScript。

这里有JavaScript 1.5的核心参考,JavaScript 1.6的新特性,JavaScript 1.7的新特性,以及JavaScript 1.8的新特性。看看所有这些实际工作的例子,是正确的。

Javascript在函数中有静态变量:

function someFunction(){
  var Static = arguments.callee;
  Static.someStaticVariable = (Static.someStaticVariable || 0) + 1;
  alert(Static.someStaticVariable);
}
someFunction() //Alerts 1
someFunction() //Alerts 2
someFunction() //Alerts 3

它在Objects内部也有静态变量:

function Obj(){
  this.Static = arguments.callee;
}
a = new Obj();
a.Static.name = "a";
b = new Obj();
alert(b.Static.name); //Alerts b