当前位置:  开发笔记 > 编程语言 > 正文

JavaScript的隐藏功能?

如何解决《JavaScript的隐藏功能?》经验,为你挑选了68个好方法。

您认为每个程序员应该知道哪些JavaScript的"隐藏功能"?

在看到以下问题的答案的优秀质量后,我认为是时候向它询问JavaScript了.

HTML的隐藏功能

CSS的隐藏功能

PHP的隐藏功能

ASP.NET的隐藏功能

C#的隐藏功能

Java的隐藏功能

Python的隐藏功能

虽然JavaScript现在可以说是最重要的客户端语言(只是问谷歌)但令人惊讶的是,大多数网络开发人员都很少理解它的实力.



1> Mark Cidade..:

您无需为函数定义任何参数.您可以只使用函数的类arguments数组对象.

function sum() {
    var retval = 0;
    for (var i = 0, len = arguments.length; i < len; ++i) {
        retval += arguments[i];
    }
    return retval;
}

sum(1, 2, 3) // returns 6


值得注意的是,虽然参数就像一个数组,但它不是一个真正的javascript数组 - 它只是一个对象.所以你不能做join(),pop(),push(),slice()等等.(如果需要,可以将它转换为真实数组:"var argArray = Array.prototype.slice.call(arguments);")
值得注意的是,访问Arguments对象是相对昂贵的 - 最好的例子是Safari,Firefox和Chrome nightlies,仅仅引用`arguments`对象使得调用函数的速度要慢得多 - 例如.if(false)参数; 会伤害性能.
同样,参数有一个"被调用者"属性,它是当前函数本身.这允许使用匿名函数进行递归,很酷!
@Vincent Robert:请注意`arguments.callee`已被弃用.
@Nathan"f(x,y,z)"看起来比"f([x,y,z])"好.
哇!真?!老实说,我不知道.这个网站真的需要一个"最喜欢的答案"功能.我肯定会添加这个.
@Nathan这个`arguments`允许你弯曲和扭曲任何现有的函数到你的意志,甚至不知道参数.试试谷歌的"Memoize Javascript"你会明白如何使用它.

2> Martin Clark..:

我可以引用道格拉斯·克罗克福德的大部分优秀书籍 JavaScript:The Good Parts.

但我会为你拿一个,总是使用===!==不是==!=

alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true

==不是传递性的.如果您使用===它将按预期为所有这些语句提供false.


如果您对动态类型感到困惑并且希望它"真正"等于,那么使用===代替==是一个很好的建议.我们这些理解动态类型的人可能继续使用==在我们知道我们想要投射的情况下,如0 ==''或0 =='0'.
令人遗憾的是,很多人都认为克罗克福德是无所不知的.当然,这个人对他的大多数批评都是正确的,但是我没有给他的东西一个像许多开发者那样的全面认可......
我是杰森的第二个警告.这本书本身非常有趣,它确实提供了很多好的建议,但DC确信他的做事方式是唯一正确的方式,其他一切都是"有缺陷的".如果您想要一些示例,请查看他对JSLint Yahoo Group的回复.
那么==和===不是关于动态类型.==确实键入了coersion,这是一个不同的野兽.如果你知道,你想要转换为字符串/数字/等,那么你应该明确地做.
我认为`==`最可怕的部分是`'\n\t\r'== 0` =>`true` ...:D
不可传递:''== 0,0 =='0',但''!='0'.如果它是传递性的,''将等于'0'.0 ==''因为类型转换是自动的,一些JS架构师认为''应该转换为0.
==的最佳用途是测试未定义时,因为undefined == null,但未定义!== null.我很少见到任何我想区分undefined和null的东西.
大多数人在第一次看到它时会认为这是语言中最糟糕的部分之一(3等于!?).我认为了解它很重要,因为它会迫使你提交JavaScript动态类型的内存.
我想我会接受它.谢谢.
我可以看到,很多人仍然误解JavaScript :)
Crockford并不完美,但他彻底改变了JS并使其成为我们其他人的可用语言.他几乎总是以坚实的理由支持他的观点.如果我有2%的时间不同意他,我认为这不是什么大问题.如果您不同意,可以使用注释自定义JSLint的规则集.

3> Gulzar Nazim..:

函数是JavaScript中的一等公民:

var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };

var sum = function(x,y,z) {
  return x+y+z;
};

alert( passFunAndApply(sum,3,4,5) ); // 12

函数编程技术可用于编写优雅的javascript.

特别是,函数可以作为参数传递,例如Array.filter()接受回调:

[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]

您还可以声明仅存在于特定函数范围内的"私有"函数:

function PrintName() {
    var privateFunction = function() { return "Steve"; };
    return privateFunction();
}


不确定这是一个隐藏的功能...更像是一个核心功能.
函数作为数据的概念绝对是我书中的重点.
在javascript中有三种方法可以生成函数:函数sum(x,y,z){return(x + y + z); }和var sum = new Function("x","y","z","return(x + y + z);"); 是其他方式.

4> Mark Cidade..:

您可以使用in运算符来检查对象中是否存在键:

var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true

如果您发现对象文字太丑陋,可以将它与无参数函数提示结合起来:

function list()
 { var x = {};
   for(var i=0; i < arguments.length; ++i) x[arguments[i]] = 0;
   return x
 }

 5 in list(1,2,3,4,5) //true


另外,要小心:in运算符还测试原型链!如果有人在Object.prototype上放了一个名为'5'的属性,那么即使你在列表中显示'5(1,2,3,4)',第二个例子也会返回true ...你最好使用hasOwnProperty方法:list(1,2,3,4).hasOwnProperty(5)将返回false,即使Object.prototype具有属性'5'.
不那么聪明,检查是否存在密钥,而不是值.列表中的x; 只有因为x [1]!= null才有效,不是因为值1在那里.
对于最通用的解决方案,可以测试一个Object是否有自己的属性,即使它被命名为"hasOwnProperty",你必须一直到:Object.prototype.hasOwnProperty.call(object,name) ;

5> CMS..:

为变量分配默认值

您可以||在赋值表达式中使用逻辑或运算符来提供默认值:

var a = b || c;

a变量将获得的价值c只有当bfalsy(如果是null,false,undefined,0,empty string,或NaN),否则a将获得的价值b.

当你想在没有提供的情况下给参数赋予默认值时,这通常在函数中很有用:

function example(arg1) {
  arg1 || (arg1 = 'default value');
}

事件处理程序中的IE回退示例:

function onClick(e) {
    e || (e = window.event);
}

以下语言功能已经使用了很长时间,所有JavaScript实现都支持它们,但在ECMAScript第5版之前它们不是规范的一部分:

debugger声明

描述于:§12.15调试器语句

此语句允许您通过以下方式以编程方式在代码中放置断点:

// ...
debugger;
// ...

如果调试器存在或处于活动状态,它将导致它立即在该行上断开.

否则,如果调试器不存在或处于活动状态,则此语句没有可观察到的影响.

多行字符串文字

描述于:§7.8.4字符串文字

var str = "This is a \
really, really \
long line!";

你必须要小心,因为旁边的字符\ 必须是行终止符,如果你有一个空格\,例如,代码看起来完全一样,但它会引发一个SyntaxError.


如果它被认为是假的,则不是.a = 0 || 42; 会给你42.这可以与Python相提并论,而不是C#的?运营商.如果你想要C#行为,做一个=(b === null)?c:b;
甜!与萤火虫一起工作.
我希望有适当的|| 仅适用于undefined.今天我被0咬了,因为我想创建重载方法的模拟,所以最后一个参数是可选的,而是使用默认值.
我不知道多行字符串文字技术.太棒了,谢谢.

6> Eugene Yokot..:

JavaScript没有块范围(但它有闭包所以让我们甚至调用它?).

var x = 1;
{
   var x = 2;
}
alert(x); // outputs 2


或者只是:(function(){var x = 2;})(); 警报(typeof x); //未定义
你总是可以做"var tmp = function(){/*block scope*/}();".语法很难看,但它有效.
这是一个很好的.这与大多数C语言非常重要.
或者如果只是Firefox,你可以使用"let":http://stackoverflow.com/questions/61088/hidden-features-of-javascript#155730

7> Patrick..:

您可以使用[]而不是访问对象属性.

这允许您查找与变量匹配的属性.

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攻击.


值得注意的是,点引用实际上是bracketref的语法糖.无论如何,根据规范,`foo.bar`的行为就像`foo ["bar"]`.还要注意,一切都是字符串属性.即使你进行数组访问,`array [4]`,4也会被转换为字符串(同样,至少根据ECMAScript v3规范)

8> Ates Goral..:

如果您正在使用Google搜索关于给定主题的合适JavaScript引用,请在查询中包含"mdc"关键字,并且您的第一个结果将来自Mozilla开发人员中心.我没有随身携带任何离线参考书或书籍.我总是使用"mdc"关键字技巧来直接找到我正在寻找的东西.例如:

谷歌:javascript数组排序mdc
(在大多数情况下你可能会省略"javascript")

更新: Mozilla开发人员中心已重命名为Mozilla Developer Network."mdc"关键字技巧仍然有效,但很快我们可能不得不开始使用"mdn"了.


哇,很棒的资源.立刻比蹩脚的w3schools好...
如果您使用的是Firefox,则甚至不需要使用Google:只需在地址栏中键入"array mdc"并按Enter键即可.
一个支持这个:http://promotejs.com/,一个基层搜索引擎优化计划,以推动MDC结果进一步提高谷歌搜索结果.
现在是MDN doc中心,所以'mdc'关键字仍然有效:)
修复了Google搜索链接.
最好的部分是这个堆栈溢出问题是如何在结果的第一页:)

9> qui..:

对某些人来说可能有点明显......

安装Firebug并使用console.log("hello").比使用随机警报()更好,这是我记得几年前做的很多.


function log(msg){if(console)console.log(msg)else alert(msg)}
始终包括:if(typeof('console')=='undefined'){console = {log:function(){}}; 然后你可以继续使用console.log,它什么都不做.
在将代码发布给可能未安装Firebug的其他人之前,不要忘记删除控制台语句.
乔希:由于未定义控制台,因此无法正常工作.您可以检查typeof console!=="undefined"或window.console.
更好的是,在带有';;;'的日志语句之前 然后缩小为你照顾它.(至少,我使用的Perl模块具有该功能,并声称它很常见.)

10> Allain Lalon..:

私人方法

对象可以具有私有方法.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    // A private method only visible from within this constructor
    function calcFullName() {
       return firstName + " " + lastName;    
    }

    // A public method available to everyone
    this.sayHello = function () {
        alert(calcFullName());
    }
}

//Usage:
var person1 = new Person("Bob", "Loblaw");
person1.sayHello();

// This fails since the method is not visible from this scope
alert(person1.calcFullName());


这不是一个私有函数 - 它更像是局部范围内的函数变量.
@Zach,确切地说!在花费数年时间使用基于类的OO语言之后,很容易忘记它们只是OO概念的一种实现.当然,尝试将基于准类的OO塞入JS的各种库也无济于事......
是的,但是根据所有操作定义,我可以想到这是一种方法.它是一个代码块,其名称可以访问实例状态,只能由该实例查看.你对私有方法的定义是什么?
只是想知道,person1是否有法律博客?;-)
+1被捕发展参考
我不认为你可以调用那个方法,因为在每个对象实例中创建了一个新函数.方法在原型中,可以更改一次以更改所有对象.添加一个事实,通过这种技术,您的对象需要更多的内存.
@Vince,这是一个实例方法.@Kieth,每个lang的实现细节都不同.应该考虑的是它是否提供必要级别的信息隐藏以被称为私有.
不只是听起来像等等等等.我在教学时一直使用这个名字.
任何具有闭包和一流功能的语言都可以做到这一点.我认为它没有把它称为"私人方法".更准确的是"你可以通过在构造函数中声明一个函数来模拟私有方法".抽象分解的地方:如果在`Person`的原型中声明一个函数,它将无法访问`calcFullName`"私有方法".将其称为"私有方法"只会让人感到困惑,并使JavaScript看起来像基于类的OOP.

11> 小智..:

在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.


在进行代码审查时,请始终查找此代码.离开",10"是一个常见的错误,在大多数测试中都没有被注意到.
@Infinity:如何重新定义fn以突出显示"编码错误"?`__parseInt = parseInt; parseInt = function(str,base){if(!base)throw new Error(69,"你的所有基地都属于我们"); return __parseInt(str,base); }`
为什么不使用`Math.floor`或`Number`?`10 === Math.floor("010"); 10 ===数字("010");`浮动:`42 === Math.floor("42.69"); 42.69 ===数字("42.69");`

12> VolkerK..:

函数是对象,因此可以具有属性.

fn = function(x) {
   // ...
}

fn.foo = 1;

fn.next = function(y) {
  //
}


这是一个非常有用的提示.例如,您可以将默认值设置为函数的属性.例如:myfunc.delay = 100; 然后用户可以更改默认值,所有函数调用都将使用新的默认值.例如:myfunc.delay = 200; MYFUNC();

13> ScottKoon..:

我不得不说自动执行功能.

(function() { alert("hi there");})();

因为Javascript 没有块作用域,所以如果要定义局部变量,可以使用自执行函数:

(function() {
  var myvar = 2;
  alert(myvar);
})();

这里,myvar不会干扰或污染全局范围,并在函数终止时消失.


是的,我将所有`.js`文件放在一个匿名的自执行函数中,并将我想要的全局内容可以附加到`window`对象中.防止全局命名空间污染.
它也适用于块范围.
它不是关于警报,而是关于同时定义和执行函数.您可以让该自执行函数返回一个值,并将该函数作为参数传递给另一个函数.
@Paul它对封装有好处.
这对什么有用?将警报置于函数外部可获得相同的结果.
这也可以用来重命名变量:(function($){...})(jQuery)将以$为单位访问全局jQuery对象.

14> pramodc84..:

知道函数预期有多少参数

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


从来不知道第一部分.太好了!
@Xavi是答案的第1部分

15> David Leonar..:

以下是一些有趣的事情:

比较NaN有什么(甚至NaN)始终是假的,包括==,<>.

NaN 代表不是数字,但如果你要求类型,它实际上返回一个数字.

Array.sort 可以采用比较器功能,并由类似快速排序的驱动程序调用(取决于实现).

正则表达式"常量"可以保持状态,就像它们匹配的最后一样.

一些JavaScript的版本允许你访问$0,$1,$2对正则表达式的成员.

null与众不同.它既不是对象,也不是布尔值,数字,字符串,也不是undefined.这有点像"替代" undefined.(注:typeof null == "object")

在最外层的上下文中,this产生否则无法命名的[Global]对象.

声明变量var,而不仅仅依赖于变量的自动声明,使运行时真正有机会优化对该变量的访问

with构造将破坏这种优化

变量名称可以包含Unicode字符.

JavaScript正则表达式实际上不是常规的.它们基于Perl的正则表达式,并且可以构建具有前瞻性的表达式,这需要花费非常长的时间来进行评估.

可以标记块并将其用作目标break.可以标记循环并将其用作目标continue.

数组不稀疏.设置其他空数组的第1000个元素应填充它undefined.(取决于实施)

if (new Boolean(false)) {...} 将执行该{...}

Javascript的正则表达式引擎是特定于实现的:例如,可以编写"非可移植"正则表达式.

[稍微更新以回应好评; 请看评论]


"数组不稀疏"取决于实现.如果设置a [1000]的值并查看[999],那么是,它是`undefined`,但这只是在查找不存在的索引时获得的默认值.如果您检查了[2000],那也将是"未定义",但这并不意味着您已经为它分配了内存.在IE8中,一些数组是密集的,有些是稀疏的,这取决于JScript引擎当时的感受.在这里阅读更多内容:http://blogs.msdn.com/jscript/archive/2008/04/08/performance-optimization-of-arrays-part-ii.aspx
null实际上是一个(特殊)对象.`typeof null`返回"object".
您还可以从以下任何位置获取[Global]对象:var glb = function(){return this; }();
浏览器中javascript中的全局对象是窗口对象.当在全局范围内做:window.a == a;
@Ates和@SF:typeof为一系列不同类型返回"object".但是一旦你知道它是如何工作的以及哪些类型被识别为"对象",它的实现至少是可靠和一致的.

16> Andy E..:

我知道我迟到了,但我无法相信+除了"将任何东西转换为数字"之外,还没有提到运营商的用处.也许这是隐藏一个功能有多好?

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


@ Nyuszika7H:你有点忽略了这一点,即强迫其他原语和对象*到*数字.当然你可以写`0xFF`,就像你写`1`而不是`+ true`一样.我建议您可以使用`+("0x"+ somevar)`替换`parseInt(somevar,16)`,如果你愿意的话.

17> Eric Schoono..:

" JavaScript中的扩展方法 "通过prototype属性.

Array.prototype.contains = function(value) {  
    for (var i = 0; i < this.length; i++) {  
        if (this[i] == value) return true;  
    }  
    return false;  
}

这将为contains所有Array对象添加一个方法.您可以使用此语法调用此方法

var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");


对于Array对象进行假设通常也被认为是一个坏主意.:(
这通常被认为是一个坏主意,因为其他代码(不是你的)可能会对Array对象做出假设.
@Breton:这不是Array类特有的,它只是一个例子.我用它来扩展新的Date().toString(); 方法,允许使用掩码字符串.*任何*对象都可以扩展,所有实例都可以获得新方法.

18> Ates Goral..:

要从对象中正确删除属性,应删除该属性,而不是仅将其设置为undefined:

var obj = { prop1: 42, prop2: 43 };

obj.prop2 = undefined;

for (var key in obj) {
    ...

属性prop2仍将是迭代的一部分.如果你想完全摆脱prop2,你应该做:

delete obj.prop2;

当您遍历属性时,属性prop2将不再出现.


请注意,delete语句并非没有特定于浏览器的怪癖.例如,如果您在IE中尝试并且该对象不是本机JS对象(即使删除您自己添加的属性),这将失败并出现大错误.它也不是用于删除变量,如删除myvar; 但我认为这在某些浏览器中有效.上面的答案中的代码似乎非常安全.

19> Shog9..:

with.

它很少使用,坦率地说,很少有用......但是,在有限的情况下,它确实有其用途.

例如:对象文字对于在对象上快速设置属性非常方便.但是,如果您需要更改现有对象的一半属性,该怎么办?

var user = 
{
   fname: 'Rocket', 
   mname: 'Aloysus',
   lname: 'Squirrel', 
   city: 'Fresno', 
   state: 'California'
};

// ...

with (user)
{
   mname = 'J';
   city = 'Frostbite Falls';
   state = 'Minnesota';
}

艾伦风暴指出,这可能是有点危险:如果用作上下文对象不具有的属性之一被分配到,它会在外部范围加以解决,有可能产生或覆盖全局变量.如果您习惯于编写代码来处理具有默认值或空值的属性未定义的对象,那么这将特别危险:

var user = 
{
   fname: "John",
// mname definition skipped - no middle name
   lname: "Doe"
};

with (user)
{
   mname = "Q"; // creates / modifies global variable "mname"
}

因此,避免使用该with语句进行此类分配可能是个好主意.

另请参阅:JavaScript的"with"语句是否有合法用途?


传统智慧应该避免使用.如果用户对象没有您提到的属性之一,那么将修改with块的伪范围之外的变量.那种方式就是错误.更多信息,请访问http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/
Douglas Crockford最近说"with"是.NET Rocks中最糟糕的JavaScript之一!播客.
阿门 - 如果我在任何我发现的JS中看到"with"语句,我会消除它并质疑编写它的开发人员,以确保他知道为什么使用它不是一件好事......"隐藏的功能?" 更像是"令人憎恶的特征".

20> Vincent Robe..:

可以在对象上调用方法(或函数),这些方法不是它们设计用于的类型.这很适合在自定义对象上调用本机(快速)方法.

var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });

此代码崩溃,因为listNodes不是Array

Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);

此代码有效,因为listNodes定义了足够的类似数组的属性(length,[] operator)sort().



21> Már Örlygsso..:

原型继承(由道格拉斯克罗克福德推广)彻底改变了你在Javascript中思考大量内容的方式.

Object.beget = (function(Function){
    return function(Object){
        Function.prototype = Object;
        return new Function;
    }
})(function(){});

这是一个杀手!可惜几乎没有人使用它.

它允许您"生成"任何对象的新实例,扩展它们,同时保持(实时)原型继承链接到其他属性.例:

var A = {
  foo : 'greetings'
};  
var B = Object.beget(A);

alert(B.foo);     // 'greetings'

// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo);     // 'hello'

A.bar = 'world';
alert(B.bar);     // 'world'


// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo);     // 'hello'

B.bar = 'universe';
alert(A.bar);     // 'world'



22> Andrey Fedor..:

有人会称之为品味,但是:

aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }

三元运算符可以被链接起来像Scheme(cond ...):

(cond (predicate  (action  ...))
      (predicate2 (action2 ...))
      (#t         default ))

可写成......

predicate  ? action( ... ) :
predicate2 ? action2( ... ) :
             default;

这非常"实用",因为它可以在没有副作用的情况下分支您的代码.所以代替:

if (predicate) {
  foo = "one";
} else if (predicate2) {
  foo = "two";
} else {
  foo = "default";
}

你可以写:

foo = predicate  ? "one" :
      predicate2 ? "two" :
                   "default";

也适用于递归,:)


我个人欢迎三元运营商.
在重新阅读时,我想指出这不是"使代码看起来像另一种语言",而是实际上简化了代码的语义含义:当你试图说"将foo设置为三个中的一个时"事情",这是一个应该以"foo = ..."开头的陈述,而不是"如果".
呃...... JavaScript确实有一个switch()语句.:-)

23> Zach..:

数字也是对象.所以你可以做很酷的事情:

// convert to base 2
(5).toString(2) // returns "101"

// provide built in iteration
Number.prototype.times = function(funct){
  if(typeof funct === 'function') {
    for(var i = 0;i < Math.floor(this);i++) {
      funct(i);
    }
  }
  return this;
}


(5).times(function(i){
  string += i+" ";
});
// string now equals "0 1 2 3 4 "

var x = 1000;

x.times(function(i){
  document.body.innerHTML += '

paragraph #'+i+'

'; }); // adds 1000 parapraphs to the document



24> Tyler..:

如何关闭 JavaScript中的闭包(类似于C#v2.0 +中的匿名方法).您可以创建一个创建函数或"表达式"的函数.

闭包示例:

//Takes a function that filters numbers and calls the function on 
//it to build up a list of numbers that satisfy the function.
function filter(filterFunction, numbers)
{
  var filteredNumbers = [];

  for (var index = 0; index < numbers.length; index++)
  {
    if (filterFunction(numbers[index]) == true)
    {
      filteredNumbers.push(numbers[index]);
    }
  }
  return filteredNumbers;
}

//Creates a function (closure) that will remember the value "lowerBound" 
//that gets passed in and keep a copy of it.
function buildGreaterThanFunction(lowerBound)
{
  return function (numberToCheck) {
    return (numberToCheck > lowerBound) ? true : false;
  };
}

var numbers = [1, 15, 20, 4, 11, 9, 77, 102, 6];

var greaterThan7 = buildGreaterThanFunction(7);
var greaterThan15 = buildGreaterThanFunction(15);

numbers = filter(greaterThan7, numbers);
alert('Greater Than 7: ' + numbers);

numbers = filter(greaterThan15, numbers);
alert('Greater Than 15: ' + numbers);


闭包和匿名函数是独立的,不同的概念.可以在不命名的情况下创建该函数具有匿名函数."创建"范围中的变量与创建的函数链接是一个闭包.简而言之,闭包更像是隐藏的全局变量.
我会说C#中的匿名函数相当于闭包,而不是相反:)
我不认为这是最好或最容易理解的闭包是什么的例子.只是说.关闭的关键在于,即使一堆变量看起来"超出范围",它们仍然可以保持对最初在该范围内定义的函数可用.在上面的例子中,这意味着即使外部函数buildGreaterThanFunction终止,内部的匿名函数仍然可以访问lowerBound变量.

25> Tyler..:

您还可以使用提示的原型链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文章修改的代码.



26> Leo..:

脱离我的头顶......

功能

arguments.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);
}

字符串

String.split可以将正则表达式作为参数:

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

String.replace可以将正则表达式作为搜索参数,将函数作为替换参数:

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


不推荐使用`arguments.callee`,它将在ECMAScript 5中抛出异常.
不,我很确定Mosaic缺少大部分.
javascript功能,是的,它们在所有主流浏览器(IE6/7,FF2/3,Opera 9 +,Safari2/3和Chrome)中实现.所有浏览器都不支持document.querySelectorAll(它是JQuery的$()的W3C版本,而Prototype的$$())

27> Ionuț G. Sta..:

您可以根据类型捕获异常.引自MDC:

try {
   myroutine(); // may throw three exceptions
} catch (e if e instanceof TypeError) {
   // statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
   // statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
   // statements to handle EvalError exceptions
} catch (e) {
   // statements to handle any unspecified exceptions
   logMyErrors(e); // pass exception object to error handler
}

注意:条件catch子句是Netscape(因此也是Mozilla/Firefox)扩展,它不是ECMAScript规范的一部分,因此除特定浏览器外不能依赖它.


我忍不住了:抓住(如果你可以,我)
阅读您引用的MDC页面中的注释:条件捕获子句是Netscape(因此也是Mozilla/Firefox)扩展,它不是ECMAScript规范的一部分,因此除特定浏览器外不能依赖它.

28> Breton..:

您可以在大多数时间使用对象而不是开关.

function getInnerText(o){
    return o === null? null : {
        string: o,
        array: o.map(getInnerText).join(""),
        object:getInnerText(o["childNodes"])
    }[typeis(o)];
}

更新:如果您担心事先评估的效率低下(为什么您在设计程序的早期担心效率?)那么您可以这样做:

function getInnerText(o){
    return o === null? null : {
        string: function() { return o;},
        array: function() { return o.map(getInnerText).join(""); },
        object: function () { return getInnerText(o["childNodes"]; ) }
    }[typeis(o)]();
}

键入(或读取)比使用开关或对象更加繁琐,但它保留了使用对象而不是开关的好处,详见下面的注释部分.一旦它长大了,这种风格也可以更直接地将它转变为适当的"类".

update2:对于ES.next提出了语法扩展,这就成了

let getInnerText = o -> ({
    string: o -> o,
    array: o -> o.map(getInnerText).join(""),
    object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);


这就是Python没有switch语句的方式.
问题是它总是评估所有情况.

29> Andreas Grec..:

迭代对象的属性时,请务必使用hasOwnProperty方法:

for (p in anObject) {
    if (anObject.hasOwnProperty(p)) {
        //Do stuff with p here
    }
}

这样做是为了您只访问anObject直接属性,而不使用原型链下的属性.



30> Chris MacDon..:

具有公共接口的私有变量

它使用一个带有自调用函数定义的巧妙小技巧.返回的对象内的所有内容都可以在公共界面中使用,而其他所有内容都是私有的.

var test = function () {
    //private members
    var x = 1;
    var y = function () {
        return x * 2;
    };
    //public interface
    return {
        setx : function (newx) {
            x = newx;
        },
        gety : function () {
            return y();
        }
    }
}();

assert(undefined == test.x);
assert(undefined == test.y);
assert(2 == test.gety());
test.setx(5);
assert(10 == test.gety());



31> 小智..:

JavaScript中的时间戳:

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

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

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


最简短的方法是聪明但很难理解,因为有人可能认为你想写+ =但错误地写了= +
当然,通过适当的格式化/间隔,避免了这种模糊性.为什么使用适当的间距这么难吃?不要写"timestamp = + new Date();",当然这令人困惑.而是写"timestamp = + new Date();".

32> username..:

您可以使用左侧的[]指定局部变量.如果您想从函数返回多个值而不创建不必要的数组,则派上用场.

function fn(){
    var cat = "meow";
    var dog = "woof";
    return [cat,dog];
};

var [cat,dog] = fn();  // Handy!

alert(cat);
alert(dog);

它是核心JS的一部分,但不知怎的,直到今年我才意识到.


这是"解构任务"; 我相信它只在运行JavaScript 1.7及更高版本的Firefox版本中得到支持.它肯定会导致Opera 10和Chrome 3以及IE出错.请参阅https://developer.mozilla.org/en/New_in_JavaScript_1.7#Destructuring_assignment
与此同时,这非常好:`function fn(){return {cat:"meow",dog:"woof"}; //方便!}; var snd = fn(); 警报(snd.cat); 警报(snd.dog);`

33> Mark Cidade..:

Javascript中的所有对象都实现为哈希表,因此可以通过索引器访问它们的属性,反之亦然.此外,您可以使用for/in运算符枚举所有属性:

var x = {a: 0};
x["a"]; //returns 0

x["b"] = 1;
x.b; //returns 1

for (p in x) document.write(p+";"); //writes "a;b;"


在从for-in循环中使用它们之前,不要忘记使用"object.hasOwnProperty(propertyName)"检查属性名称,否则您将遇到一些不需要的东西;)
此外,属性名称是字符串,如果字符串具有阻止通过点表示法使用的字符,则可以通过索引表示法访问它.例如,对象属性x ['funky prop']无法作为x.funky prop访问; x ['funky.prop']无法作为x.funky.prop访问;

34> Chris Noe..:

这个线程中有几个答案显示了如何通过其原型扩展Array对象.这是一个不好的想法,因为它打破了for (i in a)声明.

如果您不碰巧for (i in a) 在代码中的任何地方使用,那么可以吗?好吧,只有你自己的代码是你运行的唯一代码,这在浏览器中不太可能.我担心如果人们开始像这样扩展他们的Array对象,Stack Overflow会开始溢出一堆神秘的JavaScript错误.

见有帮助的细节在这里.


你不应该用for..in迭代一个数组!对数组使用标准for()循环或新的forEach()方法,并且严格用于迭代对象属性.
试着说服这个建议的现有代码;)
你只是不了解JavaScript.它不会破坏for-in循环,你不正确地构造它们.当您通过for-in进行迭代时,必须使用"yourObject.hasOwnProperty(propertyName)"检查所有属性.
for(x in y)从来没有为我的数组正常工作.我很快就学会了使用for循环的长形式.我不会让任何在我的任何工作附近的数组上使用for(in)的代码.我可以使用大量实际的编写良好的代码.
@ statictype.org - 是的,它不是 - 这就是重点.只需使用索引var进行迭代.

35> Andreas Grec..:

如果要从数组中删除元素,可以使用delete运算符,如下所示:

var numbers = [1,2,3,4,5];
delete numbers[3];
//numbers is now [1,2,3,undefined,5]

如您所见,元素已被删除,但由于元素被替换为未定义的值,因此在数组中留下了一个洞.

因此,要解决此问题,请使用splice数组方法,而不是使用delete ...如下:

var numbers = [1,2,3,4,5];
numbers.splice(3,1);
//numbers is now [1,2,3,5]

splice的第一个参数是数组[index]中的序数,第二个参数是要删除的元素数.



36> Harmen..:

在函数中,您可以返回函数本身:

function showSomething(a){
   alert(a);
   return arguments.callee;
}

// Alerts: 'a', 'b', 'c'
showSomething('a')('b')('c');

// Or what about this:
(function (a){
   alert(a);
   return arguments.callee;
}?)('a')('b')('c');????

我不知道什么时候它可能有用,无论如何,它非常奇怪和有趣:

var count = function(counter){
   alert(counter);
   if(counter < 10){
      return arguments.callee(counter+1);
   }
   return arguments.callee;
};

count(5)(9); // Will alert 5, 6, 7, 8, 9, 10 and 9, 10

实际上,Node.js 的FAB框架似乎实现了这个功能; 例如,请参阅此主题.



37> Thevs..:

JavaScript使用Date()的方式让我感到兴奋!

function isLeapYear(year) {
    return (new Date(year, 1, 29, 0, 0).getMonth() != 2);
}

这真的是"隐藏的功能".

编辑:删除"?" pollecorrecteness评论中建议的条件.是:...新日期(年,1月29日,0日,0日).getMonth()!= 2?true:false ...请查看评论以获取详细信息.



38> travis..:

这里有几个快捷方式:

var a = []; // equivalent to new Array()
var o = {}; // equivalent to new Object()



39> Seth..:

我最喜欢的技巧是使用apply对对象方法执行回调并维护正确的"this"变量.

function MakeCallback(obj, method) {
    return function() {
        method.apply(obj, arguments);
    };
}

var SomeClass = function() { 
     this.a = 1;
};
SomeClass.prototype.addXToA = function(x) {
     this.a = this.a + x;
};

var myObj = new SomeClass();

brokenCallback = myObj.addXToA;
brokenCallback(1); // Won't work, wrong "this" variable
alert(myObj.a); // 1


var myCallback = MakeCallback(myObj, myObj.addXToA);
myCallback(1);  // Works as expected because of apply
alert(myObj.a); // 2



40> slebetman..:

封闭的禅宗

其他人提到了封闭.但令人惊讶的是,有多少人知道闭包,使用闭包编写代码,但仍然对闭包真正有错误的看法.有些人将第一类函数与闭包混淆.还有一些人认为它是一种静态变量.

对我而言,闭包是一种"私人"全局变量.也就是说,一种变量,某些函数看起来像全局但其他函数看不到.现在,我知道这对于底层机制的描述是快速而松散的,但这就是它的感觉和行为.为了显示:

// Say you want three functions to share a single variable:

// Use a self-calling function to create scope:
(function(){

    var counter = 0; // this is the variable we want to share;

    // Declare global functions using function expressions:
    increment = function(){
        return ++counter;
    }
    decrement = function(){
        return --counter;
    }
    value = function(){
        return counter;
    }
})()

现在是三个函数increment,decrement并且value在不是实际全局变量的counter情况下共享counter变量.这是闭包的真正本质:

increment();
increment();
decrement();
alert(value()); // will output 1

以上并不是一个真正有用的闭包.事实上,我会说以这种方式使用它是一种反模式.但它有助于理解闭包的本质.例如,大多数人在尝试执行以下操作时会被抓住:

for (var i=1;i<=10;i++) {
    document.getElementById('span'+i).onclick = function () {
        alert('this is span number '+i);
    }
}
// ALL spans will generate alert: this span is span number 10

那是因为他们不了解封闭的本质.i当事实上函数共享一个变量时,他们认为他们正在将值传递给函数i.就像我之前说的,一种特殊的全局变量.

要解决这个问题,你需要分离*关闭:

function makeClickHandler (j) {
    return function () {alert('this is span number '+j)};
}

for (var i=1;i<=10;i++) {
    document.getElementById('span'+i).onclick = makeClickHandler(i);
}
// this works because i is passed by reference 
// (or value in this case, since it is a number)
// instead of being captured by a closure

*注意:我不知道这里的正确术语.



41> Lucent..:

您永远不必使用eval()汇编全局变量名称.

也就是说,如果你有几个全局变量(无论出于何种原因)spec_grapes, spec_apples,你就不必使用它们来访问它们eval("spec_" + var).

所有全局变量都是成员window[],所以你可以这样做window["spec_" + var].


请记住,这只是*浏览器的javascript引擎*.你可能正在运行一个独立的Javascript引擎.服务器端的JavaScript有人吗? - 只是挑剔,我知道......

42> Sebastian Ri..:

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



43> 小智..:

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

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


"function(s){alert(s);}"可以简单地用"alert"代替
它与语言无关...... :)

44> 小智..:

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

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;

好开心 :)



45> user19745..:

如果用逗号分隔语句,则几乎可以在括号之间执行任何操作:

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


你可以,但我很确定每个理智的JavaScript人都希望你画画和四分之一.
如果你想在混淆器中真的模糊,请使用中文或其他unicode字符:function喂(我){alert(我)};

46> 小智..:

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

要连接大字符串,请使用Arrays(它更快):

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"循环内部快得多.


我不同意.在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毫秒.

47> Rakesh Pai..:

truthy和falsy值的概念.你不需要做类似的事情

if(someVar === undefined || someVar === null)...

简单地说:

如果(!someVar).

每个值都有一个相应的布尔表示.


你需要小心这个.零和空字符串也转换为false.
作为推论,你应该使用if(!! x)来检查'真实性'而不是if(x)

48> Justin Love..:

函数语句和函数表达式的处理方式不同.

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

在运行代码之前解析所有函数语句 - 第一个语句中将提供JavaScript文件底部的函数.另一方面,它将无法利用某些动态上下文,例如周围with语句 - 在with解析函数时尚未执行.

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



49> bbrown..:

window.name页面更改的值仍然存在,如果在同一个域中(如果在iframe中,用于document.getElementById("your frame's ID").contentWindow.name访问它),则父窗口可以读取该值,并且仅受可用内存的限制.



50> Dave..:

创建新"对象"时,括号是可选的.

function Animal () {

}

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

一样.


我喜欢把括号留在那里因为它提醒我你实际上在调用一个函数(而'new'使它隐含地返回'this').

51> Marius..:

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


我认为你歪曲了函数一般拥有属性的能力.你所说的在技术上是正确的,但作为语言中作为一阶对象的函数的副作用.

52> Mark Cidade..:

所有函数实际上都是内置函数类型的实例,它具有一个构造函数,它接受包含函数定义的字符串,因此您可以在运行时实际定义函数,例如,连接字符串:

//e.g., createAddFunction("a","b") returns function(a,b) { return a+b; }
function createAddFunction(paramName1, paramName2)
 { return new Function( paramName1, paramName2
                       ,"return "+ paramName1 +" + "+ paramName2 +";");
 }

此外,对于用户定义的函数,Function.toString()将函数定义作为文字字符串返回.


但这通常不是必需的.在你的例子中,你可以说:return function(paramName1,paramName2){return paramName1 + paramName2; }

53> Dan..:

您可以对任何对象执行对象的方法,无论它是否具有该方法.当然它可能并不总是有效(如果该方法假定对象具有它没有的东西),但它可能非常有用.例如:

function(){
    arguments.push('foo') // This errors, arguments is not a proper array and has no push method
    Array.prototype.push.apply(arguments, ['foo']) // Works!
}



54> 小智..:

==运算符有一个非常特殊的属性,可以创建这种令人不安的平等(是的,我知道在Perl等其他动态语言中会出现这种行为,但JavaScript通常不会尝试在比较中变得聪明):

>>> 1 == true
true
>>> 0 == false
true
>>> 2 == true
false



55> Eugene Yokot..:

let.

对口VAR缺乏块作用域的是let,在JavaScript 1.7引入的.

let语句提供了一种将值与块范围内的变量相关联的方法,而不会影响块外部的同名变量的值.

let表达式允许您创建仅限于单个表达式的变量.

let定义定义了变量,其范围被约束到定义它们的块.此语法非常类似于var的语法.

您还可以使用let来建立仅存在于for循环上下文中的变量.

  function varTest() {
        var x = 31;
    if (true) {
      var x = 71;  // same variable!
      alert(x);  // 71
    }
    alert(x);  // 71
  }

  function letTest() {
    let x = 31;
    if (true) {
      let x = 71;  // different variable
      alert(x);  // 71
    }
    alert(x);  // 31
  }

截至2008年,FireFox 2.0+和Safari 3.x支持JavaScript 1.7.



56> Ates Goral..:

如果您盲目地eval()使用JSON字符串对其进行反序列化,则可能会遇到问题:

    这不安全.该字符串可能包含恶意函数调用!

    如果未将JSON字符串括在括号中,则属性名称可能会被误认为是标签,从而导致意外行为或语法错误:

    eval("{ \"foo\": 42 }"); // syntax error: invalid label
    eval("({ \"foo\": 42 })"); // OK
    



57> Breton..:

您可以将"任何具有整数属性的对象和长度属性转换为适当的数组,从而赋予它所有数组方法,如push,pop,splice,map,filter,reduce等.

Array.prototype.slice.call({"0":"foo", "1":"bar", 2:"baz", "length":3 }) 

//返回["foo","bar","baz"]

这适用于jQuery对象,html集合和来自其他帧的Array对象(作为整个数组类型事物的一种可能的解决方案).我说,如果它有一个长度属性,你可以把它变成一个数组,这没关系.除了参数对象之外,还有许多具有length属性的非数组对象.



58> Metal..:

如果您正在尝试沙箱javascript代码,并禁用每种可能的方法来将字符串评估为javascript代码,请注意阻塞所有明显的eval/document.write/new Function/setTimeout/setInterval/innerHTML和其他DOM操作不是足够.

给定任何对象o,o.constructor.constructor("alert('hi')")()将显示一个警告对话框,其中包含单词"hi".

你可以把它重写为

var Z="constructor";
Z[Z][Z]("alert('hi')")();

好玩的东西.


你可以在这里有用地提到 - 这是因为 - 任何对象的构造函数总是一些函数,并且该函数的构造函数将始终是`Function` - 可以从字符串构造函数的函数构造函数.`Function(str)`有效地返回`function(){eval(str)}`.

59> Jimmy..:

Function.toString()(隐式):

function x() {
    alert("Hello World");
}
eval ("x = " + (x + "").replace(
    'Hello World',
    'STACK OVERFLOW BWAHAHA"); x("'));
x();



60> Binoj Antony..:

微软提供给JavaScript的礼物:AJAX

AJAXCall('http://www.abcd.com/')

function AJAXCall(url) {
 var client = new XMLHttpRequest();
 client.onreadystatechange = handlerFunc;
 client.open("GET", url);
 client.send();
}

function handlerFunc() {
 if(this.readyState == 4 && this.status == 200) {
 if(this.responseXML != null)
   document.write(this.responseXML)
 }
}



61> Fabian Jakob..:

该模块模式


在没有var语句或函数外声明的变量和函数将在全局范围内定义.如果已经存在同名的变量/函数,它将被静默覆盖,这可能导致很难找到错误.一个常见的解决方案是将整个代码体包装成一个匿名函数并立即执行它.这样,所有变量/函数都在匿名函数的范围内定义,不会泄漏到全局范围.

要在全局范围内显式定义变量/函数,必须使用前缀window:

window.GLOBAL_VAR = 12;
window.global_function = function() {};



62> Tgr..:

这是jQuery的隐藏功能,而不是Javascript,但是因为永远不会有"jQuery隐藏功能"的问题......

您可以:something在jQuery中定义自己的选择器:

$.extend($.expr[':'], {
  foo: function(node, index, args, stack) {
    // decide if selectors matches node, return true or false
  }
});

对于使用的选择:foo,例如$('div.block:foo("bar,baz") span'),foo将为与选择器的已处理部分匹配的所有节点调用该函数.论点的含义:

node 保存当前节点

index 是节点集中节点的索引

args 是一个数组,如果选择器有一个参数或多个名称是有用的:

args[0]是整个选择器文本(例如:foo("bar, baz"))

args[1]是选择器名称(例如foo)

args[2]是用于包装参数的引用字符(例如"for :foo("bar, baz")),如果没有引用(:foo(bar, baz))则为空字符串,如果没有参数则为undefined

args[3]是参数,包括任何引号,(例如"bar, baz")或如果没有参数则未定义

stack 是节点集(包含在该点匹配的所有节点的数组)

true如果选择器匹配,false则该函数应返回,否则返回.

例如,以下代码将允许基于全文regexp搜索选择节点:

$.extend($.expr[':'], {
  matches: function(node, index, args, stack) {
    if (!args.re) { // args is a good place for caching
      var re = args[3];
      if (args[2]) { // get rid of quotes
        re = re.slice(1,-1);
      }
      var separator = re[0];
      var pos = re.lastIndexOf(separator);
      var modifiers = re.substr(pos+1);
      var code = re.substr(1, pos-1);
      args.re = new RegExp(code, modifiers);
    }
    return $(node).text().match(args.re);
  }
});

// find the answers on this page which contain /**/-style comments
$('.answer .post-text code:matches(!/\\*[\\s\\S]*\\*/!)');

您可以使用.filter()的回调版本达到类似的效果,但自定义选择器更灵活,通常更具可读性.


jQuery隐藏(或不广为人知)的功能:http://stackoverflow.com/questions/121965/hidden-or-not-widely-known-features-of-jquery

63> JW...:

undefined未定义.所以你可以这样做:

if (obj.field === undefined) /* ... */


如果你有一个具有该名称的变量,那么你已经失败了
"undefined"不是保留字,因此如果您有一个具有该名称的变量,这可能会失败.

64> 小智..:

访问:

http://images.google.com/images?q=disco

将此JavaScript代码粘贴到Web浏览器的地址栏中:

http://amix.dk/upload/awt/spin.txt

http://amix.dk/upload/awt/disco.txt

享受JavaScript迪斯科节目:-p



65> Eugene Yokot..:

生成器和迭代器(仅适用于Firefox 2+和Safari).

function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i < 10; i++) {
  document.write(g.next() + "
\n"); }

包含yield 关键字的函数是生成器.当你调用它时,它的形式参数绑定到实际的参数,但它的实体并没有被实际评估.而是返回一个generator-iterator.每次调用generator-iterator的 next()方法都会执行另一次迭代算法.每个步骤的值是yield关键字指定的值.可以将其yield视为返回的generator-iterator版本,指示算法的每次迭代之间的边界.每次调用时next(),生成器代码都会从后面的语句中恢复yield.

在正常使用中,迭代器对象是"不可见的"; 您不需要明确地对它们进行操作,而是使用JavaScript for...infor each...in语句自然地循环对象的键和/或值.

var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  document.write(objectWithIterator[i] + "
\n"); }



66> noah..:

这个是超级隐藏的,只是偶尔有用;-)

您可以使用原型链创建一个委托给另一个对象的对象,而无需更改原始对象.

var o1 = { foo: 1, bar: 'abc' };
function f() {}
f.prototype = o1;
o2 = new f();
assert( o2.foo === 1 );
assert( o2.bar === 'abc' );
o2.foo = 2;
o2.baz = true;
assert( o2.foo === 2 );
// o1 is unchanged by assignment to o2
assert( o1.foo === 1 );
assert( o2.baz );

这仅涵盖o1上的"简单"值.如果修改数组或其他对象,则原型不再"保护"原始对象.当你在类定义/原型中有{}或[]时,请注意.



67> Rudolf Olah..:

所有"隐藏"功能都在Mozilla wiki上:http://developer.mozilla.org/en/JavaScript.

这是JavaScript 1.5的核心参考,JavaScript 1.6中的新功能,JavaScript 1.7中的新功能,以及JavaScript 1.8中的新功能.查看所有这些实际工作且没有错误的示例.



68> Fabian Jakob..:

命名空间

在较大的JavaScript应用程序或框架中,在命名空间中组织代码会很有用.JavaScript没有模块或命名空间概念buildin,但很容易使用JavaScript对象进行模拟.这将创建一个名为的命名空间ns,并将该函数附加foo到它.

if (!window.ns) {
  window.ns = {};
}

window.ns.foo = function() {};

通常在整个项目中使用相同的全局名称空间前缀,并为每个JavaScript文件使用子名称空间.子命名空间的名称通常与文件名相匹配.

调用的文件的标题ns/button.js可能如下所示:

if (!window.ns) {
  window.ns = {};
}
if (!window.ns.button) {
  window.ns.button = {};
}

// attach methods to the ns.button namespace
window.ns.button.create = function() {};

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有