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

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

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

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


当前回答

方法(或函数)可以在不是它们设计使用的类型的对象上调用。这对于在自定义对象上调用本机(快速)方法非常有用。

var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });

这段代码崩溃是因为listNodes不是数组

Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);

这段代码之所以有效,是因为listNodes定义了足够多的类数组属性(length,[]运算符)供sort()使用。

其他回答

要正确地从对象中删除一个属性,你应该删除该属性,而不是仅仅将其设置为undefined:

var obj = { prop1: 42, prop2: 43 };

obj.prop2 = undefined;

for (var key in obj) {
    ...

prop2属性仍然是迭代的一部分。如果你想完全摆脱prop2,你应该这样做:

delete obj.prop2;

在遍历属性时,prop2属性将不再出现。

正如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 :)

如果您在google上搜索关于给定主题的像样的JavaScript参考,在查询中包含“mdc”关键字,那么您的第一个结果将来自Mozilla Developer Center。我没有随身携带任何离线参考资料或书籍。我总是使用“mdc”关键字来直接找到我要找的东西。例如:

谷歌:javascript数组排序mdc (在大多数情况下,你可以省略“javascript”)

更新:Mozilla开发者中心已重命名为Mozilla开发者网络。“mdc”关键字技巧仍然有效,但很快我们可能不得不开始使用“mdn”来代替。

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

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

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

这里有一个简单的思考“this”的方法。函数中的'This'将引用该函数的未来对象实例,通常使用operator new创建。所以很明显,内部函数的“this”永远不会指向外部函数的实例。

以上建议可以让你远离麻烦。但是你可以用“this”做更复杂的事情。


示例1:


     function DriveIn()
     {
          this.car = 'Honda';
          alert(this.food);  //'food' is the attribute of a future object 
                             //and DriveIn does not define it.
     }

     var A = {food:'chili', q:DriveIn};  //create object A whose q attribute 
                                         //is the function DriveIn;

     alert(A.car); //displays 'undefined' 
     A.q();        //displays 'chili' but also defines this.car.
     alert(A.car); //displays 'Honda' 


规则如下:

当一个函数作为一个对象的属性被调用时,在函数内部(但在任何内部函数之外)出现的任何'this'都指向该对象。

我们需要明确,即使使用operator new,“The Rule of This”也适用。在幕后,new通过对象的构造函数属性将“this”附加到对象上。


示例2:


      function Insect ()
      {
           this.bug = "bee";
           this.bugFood = function()
           {
               alert("nectar");
           }
       }

      var B = new Insect();
      alert(B.constructor); //displays "Insect"; By "The Rule of This" any
                            //ocurrence of 'this' inside Insect now refers 
                            //to B.    

为了更清楚地说明这一点,我们可以不使用operator new创建一个Insect实例。

示例3:

   
    var C = {constructor:Insect};  //Assign the constructor attribute of C, 
                                   //the value Insect.
    C.constructor();               //Call Insect through the attribute. 
                                   //C is now an Insect instance as though it 
                                   //were created with operator new. [*]
    alert(C.bug);                  //Displays "bee." 
    C.bugFood();                   //Displays "nectar." 

[*]我能辨别的唯一实际区别是,在示例3中,'constructor'是一个可枚举属性。当使用operator new时,'constructor'变成一个属性,但不是可枚举的。如果for-in操作"for(var name in object)"返回该属性的名称,则该属性是可枚举的。