JavaScript的隐藏特性?

312

1
你是不是想说:“看到了那个问题吸引的声望和观点,我想问几乎完全相同的问题来提高自己的声望”?;-) - Bobby Jack
1
当然,悲观主义者。 :) 我考虑过将这个问题变成社区问题。此外,当你获得一定数量的积分后,所有的回报都会递减。 - Allain Lalonde
1
好的,看起来你并不“需要”声望!我猜我只是对C#这个问题有些困惑——它似乎并不是这个网站旨在解决的问题类型。 - Bobby Jack
3
是的,也许不是这样,但我发现答案中的知识非常棒。如果没有 Stack Overflow(SO),要让一般的 C# 程序员在一个地方接触到所有这些知识将会很难。玩耍多年才能获得同样的宝贵经验清单。 - Allain Lalonde
我喜欢这一系列的问题;我认为答案的“digg”式系统比论坛上的“+1”更好。更容易看出社区认为最重要的是什么。我相信这对于谷歌来说也是良好的链接诱饵! - Martin Clarke
7
我已经专业编写JavaScript 10年了,从这个帖子中我学到了一些东西。谢谢Alan! - Andrew Hedges
99个回答

12

您永远不必使用 eval() 来组装全局变量名。

也就是说,如果您有几个全局变量(出于任何原因)的名称为 spec_grapes, spec_apples,您不必使用 eval("spec_" + var) 访问它们。

所有全局变量都是 window[] 的成员,所以您可以使用 window["spec_" + var]


你也可以将 "if (typeof myvar != 'undefined')" 缩短为 "if (window.myvar)"。 - BarelyFitz
7
请记住,这仅适用于浏览器的 JavaScript 引擎。你也可以运行独立的 JavaScript 引擎。服务器端 JavaScript 有人用吗?-- 我只是在挑毛病,我知道... - Esteban Küber
@voyager:我同意 - http://jaxer.org 很酷! - Lucas Jones
1
@BarelyFitz:不是这样的。变量window.myvar可以具有以下任何值:0、false、""、null或NaN。(可能还有其他值,但我认为我已经涵盖了它们。) - Jason S
在你的脚本开头,你可以简单地写上 var global = this。无论你处于什么样的上下文中,这都能起作用。 - kzh
显示剩余2条评论

11

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();

1
很奇怪没有人想到JSON吗? - Allain Lalonde

11

在使用 Firebug 的 console.log() 进行测试时,防止在 Internet Explorer 中出现烦人的错误:

function log(message) {
    (console || { log: function(s) { alert(s); }).log(message);
}

2
以下是关于编程的相关内容,请将其翻译成中文。只返回翻译后的文本:这与语言无关... :) - gblazex
3
"function(s) { alert(s); }" 可以简单替换为 "alert"。 - mickael9

10
在JavaScript中最快的循环是while(i--)。在所有浏览器中都是如此。 因此,如果您的循环元素的顺序不那么重要,您应该使用while(i--)形式:
var names = new Array(1024), i = names.length;
while(i--)
  names[i] = "John" + i;

此外,如果您需要使用for()循环,请记得始终缓存.length属性:
var birds = new Array(1024); 
for(var i = 0, j = birds.length; i < j; i++)
  birds[i].fly();

使用数组连接大字符串(更快):

var largeString = new Array(1024), i = largeString.length;
while(i--) {
  // It's faster than for() loop with largeString.push(), obviously :)
  largeString[i] = i.toString(16);
}

largeString = largeString.join("");

在循环中,它比 largeString += "something" 这种方式要快得多。


我已经使用了你的 while(i--) 的 for 循环变体有一段时间了:for (var i=names.length;i--;) {... - slebetman
2
我不同意。在Firefox中,(function(){var a=new Array(10000),i=10000;while(--i){a[i]=i}})()大约需要7毫秒,而(function(){var a=new Array(10000);for(var i=0;i<10000;i++){a[i]=i}})()则需要大约2毫秒。 - tmim

10

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

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

玩得开心 :)


依赖于构造函数属性不是一个好主意,因为它是可变的,不可靠。一旦你开始操作原型属性,很容易破坏.constructor的值。 - Breton

10

如果你用逗号分隔语句,你可以在圆括号内做几乎任何事情:

var z = ( x = "can you do crazy things with parenthesis", ( y = x.split(" "), [ y[1], y[0] ].concat( y.slice(2) ) ).join(" ") )

alert(x + "\n" + y + "\n" + z)

输出:

can you do crazy things with parenthesis
can,you,do,crazy,things,with,parenthesis
you can do crazy things with parenthesis

7
可以,但我相信每个理智的 JavaScript 开发者都会希望将你画成四分五裂。 - Allain Lalonde
2
如果您希望在混淆器中真正地使代码晦涩难懂,可以使用中文或其他Unicode字符:function 喂(我) {alert(我)}; - some

9
创建新的“对象”时,括号是可选的。
function Animal () {

}

var animal = new Animal();
var animal = new Animal;

同样的事情。


这是ECMAScript的一部分还是仅适用于Mozilla Spidermonkey引擎?(它可以在Spidermonkey shell中运行) - Jason S
不确定,我只是利用这个假设已经有一段时间了。适用于IE、IIS。 - David
2
我喜欢保留括号,因为这提醒我你实际上正在调用一个函数(而 'new' 使其隐式返回 'this')。 - Nick

9

函数声明和函数表达式的处理方式不同。

function blarg(a) {return a;} // statement
bleep = function(b) {return b;} //expression

所有函数语句都会在代码运行之前被解析 - 一个位于 JavaScript 文件底部的函数将在第一条语句中可用。但是,它无法利用某些动态上下文,比如周围的 with 语句 - 当函数被解析时,with 还没有被执行。

函数表达式在遇到它们的地方内联执行。它们在此之前不可用,但可以利用动态上下文。


9
< p >< code >window.name< /code >的值在页面更改时保持不变,如果在同一域中,则可以由父窗口读取(如果在iframe中,请使用< code >document.getElementById("your frame's ID").contentWindow.name< /code >来访问它),并且仅受可用内存限制。< /p >

9
真值和假值的概念。您不需要像这样执行操作:
如果(someVar === undefined || someVar === null)...
只需执行以下操作:
如果(!someVar)。
每个值都有相应的布尔表示。

9
请注意,这个需要小心处理。0和空字符串也会被转换为false。 - Sjoerd Visscher
2
因此,您应该使用 if (!!x) 来检查“真实性”,而不是 if (x)。 - HS.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接