你认为每个程序员都应该知道JavaScript的哪些“隐藏特性”?
在看到以下问题的优质答案后,我认为是时候向JavaScript请求它了。
HTML的隐藏特性 CSS的隐藏特性 PHP的隐藏特性 ASP的隐藏特性。网 c#的隐藏特性 Java的隐藏特性 Python的隐藏特性
尽管JavaScript可以说是目前最重要的客户端语言(问问谷歌就知道了),但令人惊讶的是,大多数web开发人员很少意识到它的强大。
你认为每个程序员都应该知道JavaScript的哪些“隐藏特性”?
在看到以下问题的优质答案后,我认为是时候向JavaScript请求它了。
HTML的隐藏特性 CSS的隐藏特性 PHP的隐藏特性 ASP的隐藏特性。网 c#的隐藏特性 Java的隐藏特性 Python的隐藏特性
尽管JavaScript可以说是目前最重要的客户端语言(问问谷歌就知道了),但令人惊讶的是,大多数web开发人员很少意识到它的强大。
当前回答
合并操作符非常酷,可以生成一些干净简洁的代码,特别是当你将它们链接在一起时:a || b || c ||“default”;问题是,由于它是通过计算为bool而不是null来工作的,如果计算为false的值是有效的,它们通常会被忽略。不用担心,在这些情况下,只要恢复到好的三元操作符就可以了。
我经常看到代码已经放弃使用全局变量而不是静态变量,所以下面是如何(在一个我认为你可以称之为泛型单例工厂的例子中):
var getInstance = function(objectName) {
if ( !getInstance.instances ) {
getInstance.instances = {};
}
if ( !getInstance.instances[objectName] ) {
getInstance.instances[objectName] = new window[objectName];
}
return getInstance.instances[objectName];
};
另外,请注意新窗口[objectName];这是通过名称一般实例化对象的关键。我两个月前才算出来的。
本着同样的精神,在使用DOM时,当我第一次初始化我要添加的任何功能时,我经常将功能参数和/或标志埋藏在DOM节点中。如果有人抱怨,我再举个例子。
令人惊讶的是,第一页上没有人提到hasOwnProperty,这是一个遗憾。当使用in进行迭代时,在迭代的容器上使用hasOwnProperty方法以确保所使用的成员名是您所期望的成员名,这是一种很好的防御性编程。
var x = [1,2,3];
for ( i in x ) {
if ( !x.hasOwnProperty(i) ) { continue; }
console.log(i, x[i]);
}
阅读这里了解更多。
最后,with几乎总是一个坏主意。
其他回答
您还可以使用前面提到的原型链spoon16扩展(继承)类和重写属性/方法。
在下面的例子中,我们创建了一个类Pet并定义了一些属性。我们还重写了继承自Object的. tostring()方法。
在此之后,我们创建了一个Dog类,它扩展了Pet并重写了. tostring()方法,再次改变了它的行为(多态性)。此外,我们还向子类添加了一些其他属性。
在此之后,我们检查继承链以显示Dog仍然是Dog类型、Pet类型和Object类型。
// Defines a Pet class constructor
function Pet(name)
{
this.getName = function() { return name; };
this.setName = function(newName) { name = newName; };
}
// Adds the Pet.toString() function for all Pet objects
Pet.prototype.toString = function()
{
return 'This pets name is: ' + this.getName();
};
// end of class Pet
// Define Dog class constructor (Dog : Pet)
function Dog(name, breed)
{
// think Dog : base(name)
Pet.call(this, name);
this.getBreed = function() { return breed; };
}
// this makes Dog.prototype inherit from Pet.prototype
Dog.prototype = new Pet();
// Currently Pet.prototype.constructor
// points to Pet. We want our Dog instances'
// constructor to point to Dog.
Dog.prototype.constructor = Dog;
// Now we override Pet.prototype.toString
Dog.prototype.toString = function()
{
return 'This dogs name is: ' + this.getName() +
', and its breed is: ' + this.getBreed();
};
// end of class Dog
var parrotty = new Pet('Parrotty the Parrot');
var dog = new Dog('Buddy', 'Great Dane');
// test the new toString()
alert(parrotty);
alert(dog);
// Testing instanceof (similar to the `is` operator)
alert('Is dog instance of Dog? ' + (dog instanceof Dog)); //true
alert('Is dog instance of Pet? ' + (dog instanceof Pet)); //true
alert('Is dog instance of Object? ' + (dog instanceof Object)); //true
这个问题的两个答案都是从Ray Djajadinata的一篇很棒的MSDN文章中修改的代码。
为变量分配默认值
你可以在赋值表达式中使用逻辑运算符||来提供一个默认值:
var a = b || c;
只有当b为false (if为null, false, undefined, 0,空字符串或NaN)时,变量a才会得到c的值,否则a将得到b的值。
这通常在函数中很有用,当你想在没有提供参数的情况下给参数一个默认值:
function example(arg1) {
arg1 || (arg1 = 'default value');
}
事件处理程序中的IE回退示例:
function onClick(e) {
e || (e = window.event);
}
以下语言特性已经伴随我们很长时间了,所有JavaScript实现都支持它们,但直到ECMAScript第5版才成为规范的一部分:
调试器语句
§12.15调试器语句描述
这个语句允许你通过以下方式在代码中添加断点:
// ...
debugger;
// ...
如果有调试器存在或处于活动状态,则会导致调试器立即在这一行上中断。
否则,如果调试器不存在或不活动,则此语句没有可观察到的效果。
多行字符串字面值
在§7.8.4字符串字面量中描述
var str = "This is a \
really, really \
long line!";
您必须小心,因为\旁边的字符必须是行结束符,例如,如果在\后面有空格,代码将看起来完全相同,但它将引发SyntaxError。
使用函数。Apply用于指定函数将作用的对象:
假设你有一个类
function myClass(){
this.fun = function(){
do something;
};
}
如果之后你这样做了:
var a = new myClass();
var b = new myClass();
myClass.fun.apply(b); //this will be like b.fun();
您甚至可以指定一个调用参数数组作为第二个参数
看这个:https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/apply
可以使用[]而不是。
这允许您查找与变量匹配的属性。
obj = {a:"test"};
var propname = "a";
var b = obj[propname]; // "test"
您还可以使用此命令获取/设置名称不是合法标识符的对象属性。
obj["class"] = "test"; // class is a reserved word; obj.class would be illegal.
obj["two words"] = "test2"; // using dot operator not possible with the space.
有些人不知道这一点,最终像这样使用eval(),这是一个非常糟糕的主意:
var propname = "a";
var a = eval("obj." + propname);
这更难阅读,更难发现错误(不能使用jslint),执行速度更慢,并可能导致XSS漏洞。
在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.