你认为每个程序员都应该知道JavaScript的哪些“隐藏特性”?
在看到以下问题的优质答案后,我认为是时候向JavaScript请求它了。
HTML的隐藏特性 CSS的隐藏特性 PHP的隐藏特性 ASP的隐藏特性。网 c#的隐藏特性 Java的隐藏特性 Python的隐藏特性
尽管JavaScript可以说是目前最重要的客户端语言(问问谷歌就知道了),但令人惊讶的是,大多数web开发人员很少意识到它的强大。
你认为每个程序员都应该知道JavaScript的哪些“隐藏特性”?
在看到以下问题的优质答案后,我认为是时候向JavaScript请求它了。
HTML的隐藏特性 CSS的隐藏特性 PHP的隐藏特性 ASP的隐藏特性。网 c#的隐藏特性 Java的隐藏特性 Python的隐藏特性
尽管JavaScript可以说是目前最重要的客户端语言(问问谷歌就知道了),但令人惊讶的是,大多数web开发人员很少意识到它的强大。
当前回答
这里有一个简单的思考“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)"返回该属性的名称,则该属性是可枚举的。
其他回答
语法糖:内联for循环闭包
var i;
for (i = 0; i < 10; i++) (function ()
{
// do something with i
}());
几乎打破了Douglas Crockford的所有代码惯例,但我认为它看起来很漂亮,从未减少:)
选择:
var i;
for (i = 0; i < 10; i++) (function (j)
{
// do something with j
}(i));
未定义就是未定义。所以你可以这样做:
if (obj.field === undefined) /* ... */
真实和虚假价值的概念。你不需要做这种事
if(someVar === undefined || someVar === zero) ...
只是做的事:
if (! someVar)。
每个值都有一个对应的布尔表示。
在我的脑海中…
功能
参数。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"
在Crockford的《Javascript: The Good Parts》中也提到过:
parseInt()是危险的。如果你给它一个字符串而不告诉它正确的进制,它可能会返回意想不到的数字。例如,parseInt('010')返回8,而不是10。传递一个base给parseInt可以使它正确工作:
parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.