加入收藏 | 设为首页 | 会员中心 | 我要投稿 佛山站长网 (https://www.0757zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

你可能不知道的一些JavaScript“奇技淫巧”

发布时间:2016-10-13 14:04:34 所属栏目:语言 来源:firstlove博客园
导读:这里记录一下以前学习各种书籍和文章里边出现的JS的小技巧,分享给大家,也供自己查阅,同时感谢那些发现创造和分享这些技巧的前辈和大牛们。

QQ截图20150414095737

这里记录一下以前学习各种书籍和文章里边出现的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(){

      var 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<b;

//会输出:aaa;bbb;false;

6、JS具备自动插入分号的能力,但是自动插入分号并不是万能的,其有三条规则:

1)只在”}”标记之前、一个或多个换行之后以及程序输入的结尾被插入;

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

这一点很重要,比如:

       a=b

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

(编辑:佛山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读