• UID12
  • 登录2016-06-14
  • 粉丝114
  • 关注50
  • 发帖1415
  • 主页
  • 金币8696枚
社区居民
最爱沙发
忠实会员
喜欢达人
原创写手
极分享 发布于2015-09-05 10:07
0/1434

你可能不知道的一些JavaScript奇技

楼层直达
这里记录一下以前学习各种书籍和文章里边出现的JS的小技巧,分享给大家,也供自己查阅,同时感谢那些发现创造和分享这些技巧的前辈和大牛们。


1、遍历一个obj的属性到数组

var a=[];
for(a[a.length] in obj);
return a;

乍一看可能比较蒙,不过仔细分析还是不难理解的。常见用法是for(var key in obj),这里key初始也是undefined的,a[a.length]整体也是undefined,所以二者其实是等价的。在for循环中,obj 的属性会依次赋值给key,同样,也依次赋值给a[a.length],这里length一直在变,就巧妙地挨个赋值给数组的每一个元素了。
2、重复字符串(如abc=>abcabc)


function repeat(target,n){          
return (new Array(n+1).join(target));    
 }


改良版本:


function repeat(target,n){          
return Array.prototype.join.call(         
 {length:n+1},target);//之所以要创建带length属性的对象,是因为调用数组原型方法时,必须是一个类数组对象,而类数组对象的条件就是length为非负整数 
  }


不新建数组,而是用拥有length属性的对象替代,然后调用数组的join方法,性能提升很大
再改进:


var repeat=(function(){          
 join=Array.prototype.join,obj={};          
return function(target,n){               
obj.length=n+1;               
return join.call(obj,target);   }     })();


利用闭包将对象和join方法缓存起来,不用每次都新建对象和寻找方法

3、for循环中,当第二项为false时会终止循环,这里并不一定存在比较,可以直接赋值,如果赋值为undefined之类的值时,转成bool值也为假,因此也会终止,比如遍历数组可以写成:


for(var i=arr.length,element;element=arr[—-i];){…}

这里,第二项一定是arr[—-i]而非arr[i--],如果是后者的话,上来就是undefined,就不会执行循环体,或者for(var i=0,element;element=arr[i++];){…}

4、NaN是JS中唯一不等于自己的值,因此可以用来判断一个变量是否真的为NaN:a!==a


5、“<”,”+”等运算符会强制符号两边的表达式执行valueOf然后比较,所以如果两边是函数或者对象,而又重写了该对象的valueOf方法,就会自动执行两边的方法。如:



var a={valueOf:function(){console.log(“aaa”);}},b={valueOf:function(){console.log(“bbb”);}};    
a&lt;b;//会输出:aaa;bbb;false;

6、JS具备自动插入分号的能力,但是自动插入分号并不是万能的,其有三条规则:
1)只在”}”标记之前、一个或多个换行之后以及程序输入的结尾被插入;

2)分号只在随后的输入标记不能被解析时插入;


   这一点很重要,比如:

  1. a=b
  2. (f());
  是不会在a=b之后自动插入分号的,因为a=b(f())是可以被解析的,因此像”(“,”[“,”+”,”-“,”/“开头的时候,需要特别注意上一行可能不会自动插入。

还有一些情况,尽管不会出现解析错误,JS仍然会强制插入分号,这就是所谓的JS语法限制产生式。它不允许在两个字符间出现换行,最危险的就是return语句,如

return
{};

会被强制插入而成为

return;
{};

类似的还有:throw语句、带有显示标签的break活着continue语句、后置自增或自减运算符


3)分号不会作为分隔符在for循环空语句的头部被自动插入

因此,最好的办法是在自己的js文件的最开始防御性地插入”;”,这样在合并js文件的时候就不会出问题了。

7、闭包。理解闭包需学会三个基本事实:

(1)JS允许你引用在当前函数意外定义的变量
(2)即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。这是因为JS的函数值包含里比调用它们时执行所需要的代码更多的信息
(3)闭包可以更新外部变量的值。这是因为闭包存储的是外部变量的引用而非值副本。如:


function box(){     var val=undefined;     return {          set:function(x){val=x;},          get:function(){return val;}     };}var b=box();b.get();//“undefined” 
b.set(5);b.get();//5


这一点很重要,比如在函数的for循环体内返回闭包或者有闭包取for循环的计数器值,那么这个闭包取到的永远是for循环结束时i的最终值,因为闭包存储的是它的引用而非当时的值副本。

8、JS没有块级作用域,因此通常情况下函数内部的所有变量都是绑定到函数作用域的,也就是说相当于都在函数一开始就声明了的,一个例外就是try/catch中的变量是块级的,只属于try/catch块。


9、众所周知,在函数内部声明函数是可以的,但是在在函数内的局部块里声明,可能会出现问题:



function f(){return “global”;}function test(x){     function f(){return “local”}     var result=[];     if(x){          result.push(f());     }     result.push(f());     return result;}test(true);//[“local”,”local”] 
test(false);//[“local”]


将函数声明到if块中:


function f(){return “global”;}function test(x){     var result=[];     if(x){          function f(){return “local”}          result.push(f());     }     result.push(f());     return result;} test(true);//? 
test(false);//?


结果会如何呢?理论上讲,JS没有块级作用域,因此f()的作用域是整个test函数,因此合理猜测应该是与上一次输出相同,全部 为”local”,可是并不是所有的JS执行环境都如此行事,有的会根据是否执行包含f的代码块来有条件地绑定函数f(绑定即意味着将该变量绑定到其最近 的作用域,而赋值是发生在代码实际执行到赋值那一步的时候进行的)。

因此最好的办法是如果要声明嵌套函数,都在其富函数的最外层声明,要么就不要声明函数,而是使用var声明和函数表达式来实现:



function f(){return “global”;}function test(x){     var result=[];     if(x){          var g=function(){return “local”}          result.push(g());     }     result.push(f());     return result;}


10、用js创建字典的时候,如果是利用对象的方式(因为JS对象的核心是一个字符串属性名称和属性值的映射表),会遇到一个问题就是原型污染,因 为获取字典属性值的时候用hasOwnProperty还好,如果用for in遍历的话,不仅会遍历对象本身,包括它的原型,因此如果在其他地方污染了Object的原型,那么for in就会产生非预期的结果,这时可能会用hasOwnProperty来先检测该对象本身是否含有属性来避免原型污染,然而更极端的情况是连 hasOwnProperty这个原型方法都有可能被污染。避免原型污染的方法是在创建字典对象的时候用Object.create(null)来创建一 个完全空对象,这个对象没有原型,这个方法是ES5的,在没有这个方法可用的时候,最好是创建字典类,然后在字典类里用数组来存储有序集合,自己维护这个 集合。

11、JS中的类数组对象可以享用数组的大部分原型方法如map等,类数组对象是指满足两个条件的对象:一是具备合理范围值内的length属性, 二是length属性大于该对象的最大索引,索引是一个合理范围的证书,它的字符串表示的是对象的一个key;但是数组的一个原型方法contact是不 能被类数组对象调用的,因此需要先用[].slice.call把类数组对象转换为真正的数组比如[].slice.call(arguments)。


12、并不是所有时候都需要继承,继承也不是完美的,有时候会创造比他能解决的更多的问题,特别是当层次关系没那么明显的时候,这时候应该多用结构 类型(又叫鸭子类型,如果它看起来像鸭子、游泳像鸭子并且叫声像鸭子,那么它就是鸭子),用结构类型设计灵活的对象接口的时候,不需要创建类工厂来返回类 的实例,而是直接返回对象,对象具备预期的方法和属性,比如:



SomeObj.someWidget=function(opts){     return {          a:blabla,          b:function(){...},          c:blabla     }}

原文链接:http://www.cnblogs.com/dson/p/4415278.html

0人打赏
您需要登录后才可以回帖
发表回复
极贡献
技术问答
专题荟萃
程序人生
视觉设计
Android开发
iOS开发
编程语言
前端开发
后端开发
服务器架构
软件测试
运维方案
创业路上



最热文章墙

  • 80963/379   【精品推荐】200多种Android动画效果的强悍框架,太全了,不看这个,再有动画的问题,不理你了^@^

  • 45957/191   情人节福利,程序员表白的正确姿势:改几行代码就变成自己的表白了

  • 45592/0   Python爬虫:常用浏览器的useragent

  • 42133/261   【精品推荐】Android版产品级的音乐播放器源码,功能太强大了,最好的产品原型有木有?

  • 39100/145   省时省力的Android组件群来了,非常棒的原型参考

  • 30574/143   2016抢红包软件及源码

  • 29601/71   原创表白APP,以程序员的姿势备战新年后的7夕,持续完善中!

  • 29488/2   超全!整理常用的iOS第三方资源

  • 24862/161   Android版类似UC浏览器:非常赞,产品级的源码

  • 23074/31   麻省理工的一帮疯子,真的实现了随意操控万物!(绝对黑科技)

  • 22768/26   Android工程师面试题大全

  • 22738/27   2016程序员跳槽全攻略

  • 22092/10   GitHub上排名前50的iOS项目:总有一款你用得着

  • 21089/21   码魂:程序员的牛B漫画

  • 19329/85   Android小而全的博客源码:非常适合全面掌握开发技巧

  • 19328/74   【持续更新中】Android福利贴(二):资料源码大放送

  • 19186/43   一个绚丽的loading动效分析与实现!

  • 19115/10   2016年最全的Android面试考题+答案 精编版

  • 18896/3   吐槽那些程序员的搞笑牛逼注释

  • 17885/45   惊艳的App引导页:背景图片切换加各个页面动画效果

  • 17814/104   Android带弹幕的视频播放器源码,来自大名鼎鼎的Bilibili弹幕网站

  • 17768/82   仿京东商城客户端Android最新版,不错的原型和学习资料

  • 17756/1   iOS 动画总结

  • 17411/25   个人收集的Android 各类功能源代码

  • 16923/5   新一代Android渠道打包工具:1000个渠道包只需要5秒

  • 16896/23   Android福利第三波【Android电子书】

  • 16716/1   iOS中文版资源库,非常全

  • 16712/81   【精品推荐】类似360安全卫士安Android源码:非常赞的产品原型

  • 16655/54   基于瀑布流的美女图片浏览App,有注释的源代码

  • 16520/18   用JavaScript 来开发iOS和Android 原生应用:React Native开源框架中文版来啦

  • 16500/10   女程序员的梦,众网友的神回复

  • 16227/23   珍藏多年的素材,灵感搜寻网站

  • 16222/11   年会上现场review代码是怎么样的体验!

  • 15879/19   65条最常用正则表达式,你要的都在这里了

  • 15001/16   基于Android支付宝支付设计和开发方案

  • 14416/11   有木有这样一张酷图帮你集齐所有git命令超实用

  • 14360/18   什么是真正的黑客:收获12200+Stars,人气远超微软开源VS

  • 14157/47   在线音乐播放器完整版(商用级的源码):非常赞,可听免费高品质专辑

  • 13977/62   【技巧一】搭配Android Studio,如何实现App远程真机debug?

  • 13841/0   GitHub iOS 库和框架Top100 

  • 13689/7   用程序员的姿势抢过年的火车票

  • 13663/7   一张图搞定iOS学习路线,非常全面

  • 13310/10   成为Java顶尖程序员 ,看这11本书就够了

  • 13243/10   微信支付终于成功了(安卓,iOS),在此分享

  • 13124/18   一张图搞定Android学习路线,非常全面

  • 12980/29   【持续更新中】Android福利贴(一):资料源码

  • 12886/4   基于Node.js的强大爬虫,能直接发布抓取的文章哦

  • 12705/4   46 个非常有用的 PHP 代码片段

  • 12161/3   即时通信第三方库

  • 11578/9   流媒体视频直播方案

  • 11549/18   八个最优秀的Android Studio插件

  • 11392/9   B站建开源工作组:APP想支持炫酷弹幕的看过来

  • 11230/2   【精品推荐】高质量PHP代码的50个实用技巧:非常值得收藏

  • 11152/9   烧了5亿美金,这家神秘的公司即将颠覆人类未来!

  • 11084/12   中国黑客的隐秘江湖:攻守对立,顶尖高手月入千万美元

  • 10587/1   基于node-webkit跨平台应用案例集之(一)

  • 10340/6   开箱即用!Android四款系统架构工具

  • 10133/11   十大技巧快速提升Android应用开发性能

  • 10124/4   10款GitHub上最火爆的国产开源项目——可以媲美西半球

  • 10079/2   Android性能优化视频,文档以及工具

  • 返回顶部