源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

有关JavaScript的10个怪癖和秘密分享

  • 时间:2021-10-21 21:00 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:有关JavaScript的10个怪癖和秘密分享
原文作者:[url=http://www.mitya.co.uk/]Andy Croxall[/url] 原文链接:[url=http://coding.smashingmagazine.com/2011/05/30/10-oddities-and-secrets-about-javascript/]Ten Oddities And Secrets About JavaScript[/url] 翻译编辑:[url=http://www.zhangxinxu.com/]张鑫旭[/url]  数据类型和定义 [b]  1. Null是个对象[/b]   JavaScript众多类型中有个Null类型,它有个唯一的值null, 即它的字面量,定义为完全没有任何意义的值。其表现得像个对象,如下检测代码:
[url=http://www.mozilla.org/js/language/E262-3.pdf]section 11.9.3 of the ECMA-262[/url] 正则表达式   4. replace()可以接受回调函数   这是JavaScript最鲜为人知的秘密之一,v1.3中首次引入。大部分情况下,replace()的使用类似下面:
[u]复制代码[/u] 代码如下:
alert('10 13 21 48 52'.replace(/\d+/g, '*')); //用 * 替换所有的数字
  这是一个简单的替换,一个字符串,一个星号。但是,如果我们希望在替换发生的时候有更多的控制,该怎么办呢?我们只希望替换30以下的数值,该怎么办呢?此时如果仅仅依靠正则表达式是鞭长莫及的。我们需要借助回调函数的东风对每个匹配进行处理。
[u]复制代码[/u] 代码如下:
alert('10 13 21 48 52'.replace(/\d+/g, function(match) { return parseInt(match) <30?'*' : match; }));
  当每个匹配完成的时候,JavaScript应用回调函数,传递匹配内容给match参数。然后,根据回调函数里面的过滤规则,要么返回星号,要么返回匹配本身(无替换发生)。 如下截图: [img]http://files.jb51.net/upload/201108/20110828200914507.png[/img] 5. 正则表达式:不只是match和replace   不少javascript工程师都是只通过match和replace和正则表达式打交道。但JavaScript所定义的正则表达式相关方法远不止这两个。   其中值得一提的是test(),其工作方式类似match(),但是返回值却不一样:test()返回的是布尔型,用来验证是否匹配,执行速度高于match()。
[u]复制代码[/u] 代码如下:
alert(/\w{3,}/.test('Hello')); //弹出 'true'
  上面行代码用来验证字符串是否有三个以上普通字符,显然"hello"是符合要求的,所以弹出true。 结果如下截图: [img]http://files.jb51.net/upload/201108/20110828200914105.png[/img]   我们还应注意RegExp对象,你可以用此创建动态正则表达式对象,例如:
[u]复制代码[/u] 代码如下:
function findWord(word, string) { var instancesOfWord = string.match(new RegExp('\\b'+word+'\\b', 'ig')); alert(instancesOfWord); } findWord('car', 'Carl went to buy a car but had forgotten his credit card.');
这儿,我们基于参数word动态创建了匹配验证。这段测试代码作用是不区分大小选的情况下选择car这个单词。眼睛一扫而过,测试英文句子中只有一个单词是car,因此这里的演出仅一个单词。\b是用来表示单词边界的。   结果如下截图: [img]http://files.jb51.net/upload/201108/20110828200914445.png[/img] 函数和作用域   6. 你可以冒充作用域   作用域这玩意是用来决定什么变量是可用的,独立的JavaScript(如JavaScript不是运行中函数中)在window对象的全局作用域下操作,window对象在任何情况下都可以访问。然而函数中声明的局部变量只能在该函数中使用。
[u]复制代码[/u] 代码如下:
var animal ='dog'; function getAnimal(adjective) { alert(adjective+''+this.animal); } getAnimal('lovely'); //弹出 'lovely dog'
  这儿我们的变量和函数都声明在全局作用域中。因为this指向当前作用域,在这个例子中就是window。因此,该函数寻找window.animal,也就是'dog'了。到目前为止,一切正常。然而,实际上,我们可以让函数运行在不同的作用域下,而忽视其本身的作用域。我们可以用一个内置的称为call()的方法来实现作用域的冒充。
[u]复制代码[/u] 代码如下:
var animal ='dog'; function getAnimal(adjective) { alert(adjective+''+this.animal); }; var myObj = {animal: 'camel'}; getAnimal.call(myObj, 'lovely'); //弹出 'lovely camel'
  call()方法中的第一个参数可以冒充函数中的this,因此,这里的this.animal实际上就是myObj.animal,也就是'camel'了。后面的参数就作为普通参数传给函数体。   另外一个与之相关的是apply()方法,其作用于call()一样,不同之处在于,传递给函数的参数是以数组形式表示的,而不是独立的变量们。所以,上面的测试代码如果用apply()表示就是:
[u]复制代码[/u] 代码如下:
getAnimal.apply(myObj, ['lovely']); //函数参数以数组形式发送
demo页面中,点击第一个按钮的结果如下截图: [img]http://files.jb51.net/upload/201108/20110828200914167.png[/img]   点击第二个和第三个按钮的结果如下: [img]http://files.jb51.net/upload/201108/20110828200915334.png[/img] 7. 函数可以执行其本身   下面这个是很OK的:
[u]复制代码[/u] 代码如下:
(function() { alert('hello'); })(); //弹出 'hello'
  这里的解析足够简单:声明一个函数,然后因为()解析立即执行它。你可能会奇怪为何要这么做(指直接屁股后面()调用),这看上去是有点自相矛盾的:函数包含的通常是我们想稍后执行的代码,而不是当下解析即执行的,否则,我们就没有必要把代码放在函数中。   另外一个执行函数自身(self-executing functions (SEFs))的不错使用是为在延迟代码中使用绑定变量值,例如事件的回调(callback),超时执行(timeouts)和间隔执行(intervals)。如下例子:
[u]复制代码[/u] 代码如下:
var someVar ='hello'; setTimeout(function() { alert(someVar); }, 1000); var someVar ='goodbye';
  Newbies在论坛里总问这里timeout的弹出为什么是goodbye而不是hello?答案就timeout中的回调函数直到其运行的时候才去赋值someVar变量的值。而那个时候,someVar已经被goodbye重写了好长时间了。   SEFs提供了一个解决此问题的方法。不是像上面一样含蓄地指定timeout回调,而是直接将someVar值以参数的形式传进去。效果显著,这意味着我们传入并孤立了someVar值,保护其无论后面是地震海啸还是女朋友发飙咆哮都不会改变。
[u]复制代码[/u] 代码如下:
var someVar = 'hello'; setTimeout((function(someVar) { returnfunction() { alert(someVar); } })(someVar), 1000); var someVar ='goodbye';
  风水轮流转,这次,这里的弹出就是hello了。这就是函数参数和外部变量的点差别了哈。 例如,最后一个按钮点击后的弹出如下: [img]http://files.jb51.net/upload/201108/20110828200915749.png[/img] 浏览器   8. FireFox以RGB格式读与返回颜色而非Hex   直到现在我都没有真正理解为何Mozilla会这样子。为了有个清晰的认识,看下面这个例子:
[u]复制代码[/u] 代码如下:
<!-- #somePara { color: #f90; } --> <p id="somePara">Hello, world!</p> <script> var ie = navigator.appVersion.indexOf('MSIE') !=-1; var p = document.getElementById('somePara'); alert(ie ? p.currentStyle.color : getComputedStyle(p, null).color); </script>
  大部分浏览器弹出的结果是ff9900,而FireFox的结果却是rgb(255, 153, 0),RGB的形式。经常,处理颜色的时候,我们需要花费不少代码将RGB颜色转为Hex。 下面是上面代码在不同浏览器下的结果: [img]http://files.jb51.net/upload/201108/20110828200915180.png[/img] [img]http://files.jb51.net/upload/201108/20110828200915341.png[/img] 其它杂七杂八   9. 0.1 + 0.2 !== 0.3   这个古怪的问题不只会出现在JavaScript中,这是计算机科学中一个普遍存在的问题,影响了很多的语言。标题等式输出的结果是0.30000000000000004。   这是个被称为机器精度的问题。当JavaScript尝试执行(0.1 + 0.2)这行代码的时候,会把值转换成它们喜欢的二进制口味。这就是问题的起源,0.1实际上并不是0.1,而是其二进制形式。从本质上将,当你写下这些值的时候,它们注定要失去精度。你可能只是希望得到个简单的两位小数,但你得到的(根据Chris Pine的注解)是二进制浮点计算。好比你想把一段应该翻译成中文简体,结果出来的却是繁体,其中还是有差异是不一样的。 一般处理与此相关的问题有两个做法: 转换成整数再计算,计算完毕再转换成希望的小数内容 调整你的逻辑,设定允许范围为不是指定结果。   例如,我们不应该下面这样:
[u]复制代码[/u] 代码如下:
var num1=0.1, num2=0.2, shouldEqual=0.3; alert(num1 + num2 == shouldEqual); //false
  而可以试试这样:
[u]复制代码[/u] 代码如下:
alert(num1 + num2 > shouldEqual - 0.001&& num1 + num2 < shouldEqual +0.001); //true
  10. 未定义(undefined)可以被定义(defined)   我们以一个和风细雨的小古怪结束。听起来可能有点奇怪,undefined并不是JavaScript中的保留字,尽管它有特殊的意义,并且是唯一的方法确定变量是否未定义。因此:
[u]复制代码[/u] 代码如下:
var someVar; alert(someVar == undefined); //显示 true
  目前为止,一切看上去风平浪静,正常无比,但剧情总是很狗血:
[u]复制代码[/u] 代码如下:
undefined ="I'm not undefined!"; var someVar; alert(someVar == undefined); //显示 false!
  这就是为什么jQuery源码中最外部的闭包函数要有个并没有传入的undefined参数,目的就是保护undefined不要被外部的些不良乘虚而入。 [img]http://files.jb51.net/upload/201108/20110828200915981.png[/img]
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部