你认为每个程序员都应该知道哪些JavaScript“隐藏功能”?
在看过以下问题的优秀答案之后,我想是时候问一下JavaScript了。
虽然JavaScript现在可以说是最重要的客户端语言(只需询问谷歌),但令人惊讶的是,大多数Web开发人员很少欣赏它真正的强大之处。
你认为每个程序员都应该知道哪些JavaScript“隐藏功能”?
在看过以下问题的优秀答案之后,我想是时候问一下JavaScript了。
虽然JavaScript现在可以说是最重要的客户端语言(只需询问谷歌),但令人惊讶的是,大多数Web开发人员很少欣赏它真正的强大之处。
在Crockford的《Javascript: The Good Parts》中也提到:
parseInt()
是危险的。如果你传递一个没有告诉它正确基数的字符串,它可能会返回意外的数字。例如,parseInt('010')
返回8而不是10。将基数传递给parseInt可以使其正常工作:
parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.
Math.floor
或Number
?
10 === Math.floor("010"); 10 === Number("010");
浮点数:
42 === Math.floor("42.69"); 42.69 === Number("42.69");
- just somebodyparseInt
函数很容易被制造成一些不太无害的东西。 - bob-the-destroyer__parseInt = parseInt; parseInt = function (str, base) { if (!base) throw new Error(69, "All your base belong to us"); return __parseInt(str, base); }
@Infinity建议将这个函数重新定义为突出显示“编码错误”,你可以使用以下翻译: "将该函数重新定义以强调“编码错误”,请参考下方代码: __parseInt = parseInt; parseInt = function (str, base) { if (!base) throw new Error(69, "All your base belong to us"); return __parseInt(str, base); }
" - JBRWilkinson函数是对象,因此可以拥有属性。
fn = function(x){ //... }
fn.foo = 1;
fn.next = function(y){ // }
我必须说自执行函数。
(function() { alert("hi there");})();
因为 Javascript 没有块级作用域,所以如果你想定义局部变量,可以使用自执行函数:
因为 JavaScript 没有块级作用域,所以如果你想要定义局部变量,可以使用一个立即执行函数:
(function() {
var myvar = 2;
alert(myvar);
})();
这里,myvar
不会干扰或污染全局范围,并且在函数终止时消失。
.js
文件都封装在一个匿名自执行函数中,并将任何我想要全局访问的内容附加到window
对象上。这样可以防止全局命名空间污染。 - cdmckay知道函数期望的参数数量
function add_nums(num1, num2, num3 ){
return num1 + num2 + num3;
}
add_nums.length // 3 is the number of parameters expected.
知道函数接收了多少个参数
function add_many_nums(){
return arguments.length;
}
add_many_nums(2,1,122,12,21,89); //returns 6
以下是一些有趣的内容:
NaN
与任何东西(包括自己)进行比较,结果总是 false,这包括 ==
、<
和 >
。NaN
代表着不是一个数字,但如果你询问它的类型,它实际上返回的是一个数字。Array.sort
可以采用比较函数,并由类似快速排序的驱动程序调用(取决于具体实现)。$0
、$1
、$2
成员。null
不像其他任何东西。它既不是对象、布尔值、数字、字符串也不是 undefined
。它有点像“备用”的 undefined
。(注意:typeof null == "object"
)this
返回无法命名的 [Global] 对象。var
声明变量,而不是依靠变量的自动声明,可以让运行时真正优化对该变量的访问。with
结构会破坏这种优化。break
的目标。循环可以标记并用作 continue
的目标。undefined
。(取决于具体实现)if (new Boolean(false)) {...}
将执行 {...}
块typeof null
返回 "object"。 - Ates Goral我知道我有点晚了,但我真的不敢相信+
操作符的有用性仅仅被提到“将任何东西转换为数字”。也许这就是这个功能有多么隐蔽的原因?
// Quick hex to dec conversion:
+"0xFF"; // -> 255
// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();
// Safer parsing than parseFloat()/parseInt()
parseInt("1,000"); // -> 1, not 1000
+"1,000"; // -> NaN, much better for testing user input
parseInt("010"); // -> 8, because of the octal literal prefix
+"010"; // -> 10, `Number()` doesn't parse octal literals
// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null; // -> 0;
// Boolean to integer
+true; // -> 1;
+false; // -> 0;
// Other useful tidbits:
+"1e10"; // -> 10000000000
+"1e-4"; // -> 0.0001
+"-12"; // -> -12
Number()
来完成所有这些操作,但是+
运算符更加优美!valueOf()
方法来为对象定义数值返回值。对该对象执行的任何数字转换都不会导致NaN
,而是valueOf()
方法的返回值:var rnd = {
"valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd; // -> 442;
+rnd; // -> 727;
+rnd; // -> 718;
0xFF
等,不需要使用+"0xFF"
。 - alexia0xFF
,就像你可以写1
代替+true
一样。我建议如果需要的话,可以使用+("0x"+somevar)
来替代parseInt(somevar, 16)
。 - Andy E通过原型属性在JavaScript中实现扩展方法。
Array.prototype.contains = function(value) {
for (var i = 0; i < this.length; i++) {
if (this[i] == value) return true;
}
return false;
}
这将为所有Array
对象添加一个contains
方法。您可以使用以下语法调用此方法
var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");
要正确地从对象中移除属性,你应该删除该属性,而不仅仅将其设置为undefined:
var obj = { prop1: 42, prop2: 43 };
obj.prop2 = undefined;
for (var key in obj) {
...
属性 prop2 仍将成为迭代的一部分。如果要完全摆脱 prop2,则应执行以下操作:
delete obj.prop2;
当你遍历属性时,属性prop2将不再出现。
with
.
它很少被使用,而且说实话,也很少有用... 但是,在有限的情况下,它确实有其用途。
例如:对象字面量非常方便快速地设置一个 新的 对象的属性。但是如果你需要更改现有对象的 一半 属性呢?
var user =
{
fname: 'Rocket',
mname: 'Aloysus',
lname: 'Squirrel',
city: 'Fresno',
state: 'California'
};
// ...
with (user)
{
mname = 'J';
city = 'Frostbite Falls';
state = 'Minnesota';
}
Alan Storm指出这可能有一定危险性:如果作为上下文使用的对象没有其中一个被赋值的属性,它将在外部范围中解决,可能会创建或覆盖全局变量。 如果你习惯于编写用于处理对象的代码,其中留空默认值的属性未定义,则这尤其危险:
var user =
{
fname: "John",
// mname definition skipped - no middle name
lname: "Doe"
};
with (user)
{
mname = "Q"; // creates / modifies global variable "mname"
}
因此,对于这种赋值情况,避免使用with
语句可能是一个好主意。
with
的定义方式使其无法进行优化。这个演示提供了关于为什么with
很慢的信息。在旧版本的IE中,所有语句都很慢,所以with
并不比其他语句更慢。 - dolmen方法(或函数)可以在不是它们设计用于处理的类型的对象上调用。这对于在自定义对象上调用本地(快速)方法非常有用。
var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });
代码崩溃的原因是listNodes
不是一个Array
。
Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);
这段代码之所以可行,是因为listNodes
定义了足够类似数组的属性(如length、[]运算符),让sort()
可以使用。