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

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

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

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


当前回答

我最喜欢的方法之一是构造函数类型检查:

function getObjectType( obj ) {  
    return obj.constructor.name;  
}  

window.onload = function() {  
    alert( getObjectType( "Hello World!" ) );  
    function Cat() {  
        // some code here...  
    }  
    alert( getObjectType( new Cat() ) );  
}

因此,您可以根据构造函数获得真正的对象类型,而不是经常使用typeof关键字获得的陈旧的[Object对象]。

另一种方法是使用变量参数作为“重载”函数的一种方式。你所做的只是使用一个表达式来检测参数的数量并返回重载输出:

function myFunction( message, iteration ) {  
    if ( arguments.length == 2 ) {  
        for ( i = 0; i < iteration; i++ ) {  
            alert( message );  
        }  
    } else {  
        alert( message );  
    }  
}  

window.onload = function() {  
    myFunction( "Hello World!", 3 );  
}

最后,我要说的是赋值运算符速记。我从jQuery框架的源代码中了解到这一点…老办法:

var a, b, c, d;
b = a;
c = b;
d = c;

新的(简写)方式:

var a, b, c, d;
d = c = b = a;

很有趣。

其他回答

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

JavaScript使用了一个简单的对象文字:

var x = { intValue: 5, strValue: "foo" };

这将构造一个完整的对象。

JavaScript使用基于原型的面向对象,并提供了在运行时扩展类型的能力:

String.prototype.doubleLength = function() {
    return this.length * 2;
}

alert("foo".doubleLength());

对象将对不包含它自身的属性的所有访问委托给它的“原型”,另一个对象。这可以用来实现继承,但实际上更强大(即使更麻烦):

/* "Constructor" */
function foo() {
    this.intValue = 5;
}

/* Create the prototype that includes everything
 * common to all objects created be the foo function.
 */
foo.prototype = {
    method: function() {
        alert(this.intValue);
    }
}

var f = new foo();
f.method();

您可以动态地重新定义运行时环境的大部分内容,例如修改Array构造函数或定义undefined。并不是说你应该这样做,但它可以是一个强大的功能。

一种稍微不那么危险的形式是向现有对象添加helper方法。例如,你可以让IE6在数组上“原生”支持indexOf。

JavaScript中的时间戳:

// Usual Way
var d = new Date();
timestamp = d.getTime();

// Shorter Way
timestamp = (new Date()).getTime();

// Shortest Way
timestamp = +new Date();

在我的脑海中…

功能

参数。Callee指的是承载“arguments”变量的函数,所以它可以用来递归匿名函数:

var recurse = function() {
  if (condition) arguments.callee(); //calls recurse() again
}

如果你想做这样的事情,这很有用:

//do something to all array items within an array recursively
myArray.forEach(function(item) {
  if (item instanceof Array) item.forEach(arguments.callee)
  else {/*...*/}
})

对象

关于对象成员有一个有趣的事情:他们可以有任何字符串作为他们的名字:

//these are normal object members
var obj = {
  a : function() {},
  b : function() {}
}
//but we can do this too
var rules = {
  ".layout .widget" : function(element) {},
  "a[href]" : function(element) {}
}
/* 
this snippet searches the page for elements that
match the CSS selectors and applies the respective function to them:
*/
for (var item in rules) {
  var elements = document.querySelectorAll(rules[item]);
  for (var e, i = 0; e = elements[i++];) rules[item](e);
}

字符串

字符串。Split可以将正则表达式作为参数:

"hello world   with  spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]

字符串。Replace可以将正则表达式作为搜索参数,将函数作为替换参数:

var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"