• JS有哪些变态语法


    JS作为一门如此灵活的语言,自然在编码时给我们带来了很多方便,但方便的同时,也衍生出了很多变态的语法,下面我们来梳理一些常见的变态语法,希望你下次在某位大牛的代码中看到这样的东西,不要惊掉下巴。

      NO.1

    ——————————————————————————————————————

      Number.prototype.add = function(n){

      return this+n;

    }

      2"add"
    ——————————————————————————————————————

      最后一句话是什么玩意儿?好像没看懂呢? 我们来运行一下看看

      我擦? 它居然执行了?结果是5,看上去似乎对2和3做了加法。

      不是说变量名不能数字开头么?这是怎么回事?浏览器抽风了?

      实际上js有很多不能说的秘密,其中一个就叫做自动装箱,这是引用java里的叫法。也就是说,当我们试图2[“add”]的时候,这个数字2已经不再是2了,它被自动转换成了Number对象,跟java中的包装类型是一个意思。

    等价于这样写:

      new Number(2)

      而对象是可以通过[“prop"]这种形式来获取属性的,于是我们就不难推理了

      2["add"] 相当于 new Number(2).add

      最终变成

      new Number(2).add(3);

      结果是 5

    NO.2

    —————————————————————————————————————— +function(){;}()
    ——————————————————————————————————————

      这又是个什么玩意儿?函数前面带个+号? 这难道是自动类型转换?等等,里面是个;号? 后面还有一对( )?

      先不要着急惊讶,其实还有很多,例如:

      -function(){;}()

      !function(){;}()

      ~function(){;}()

      void function(){;}()

      new function(){;}()

      delete function(){;}()

      var i = function(){;}()

      1 && function(){;}()

      0 || function(){;}()

      1 & function(){;}()

      1 | function(){;}()

      1 ^ function(){;}()

      1, function(){;}()

      我靠!这些丧尽天良的写法是谁发明的?!你给我站出来,我保证不打死你!

      (此处作者冷静了5分钟)

      接下来说说它的原理吧

      首先 ;号本身也是一条语句,相信大多数同学应该是知道的,就不多说了。其次,一个函数的自调用,如果写成这样:

      错误的原因在于,函数声明和函数调用是不可以混在一起的,所以通常的写法是:

      这并不是把函数当成了一个整体来运行,这里其实还有一个不能说的秘密

      ( )这个符号,在js里是运算符。(A)的结果是返回表达式A

      所以它的出现,让这个匿名函数从声明变成了执行,也就是编译期间浏览器不会提前准备它,自然就没有语法错误。而5分钟前我们看到的那些丧心病狂的写法,其实原理都一样,通过运算符把声明变成执行。当然这些符号都不会影响函数的正常执行结果。

      但是问题又来了,这种泯灭人性的写法,现在居然还挺常见的,例如:

      没错,这就是著名的bootstrap的js源码,连它都是这么写的,莫非真有什么好处?

      通过在网上查询大量的资料,我还真发现有人专门对此做了研究,将上面这些写法全部在各个浏览器中间做了压力测试,发现+function( ){;}( ) 执行速度最快,比(function( ){})( )要快出好几倍

      而 new function( ){;}( ) 执行速度最慢。

      不过为了追求效率而把代码写成这样到底值不值,那只能你自己去判断了。

    NO.3

    ——————————————————————————————————————
    !!a
    ——————————————————————————————————————

      这又是什么鬼啊

      !!a 实际上等价于 a || false

      由于js中所有的内容都是可以跟布尔类型互换的,这也是js特别让人费解的地方,比如

      if(window.VBArray){…}

      可以用来判断IE浏览器,因为对象存在时,等价于true,undefined等价于false,但是!很多时候我们判断一个属性是否存在,并不需要马上作出反应,而是将结果告知他人,比如说有个函数,test(hasSuperman),函数规定调用时需要传入一个布尔类型,告知它superman是否存在,你可能会这样写:

      if(window.superman){

      test(true);

      } else {

      test(false);

      }

      但你最好不要这么写:

      test(window.superman);

      因为你并不知道test函数内部发生了什么,所以很难预料会不会产生错误,因此最好的写法是这样:

      test(!!window.superman);

      通过两次取反,保证了值没有变化,但类型已经被转为了布尔类型。好吧,似乎这么写还有点道理。

    NO.4 最短IE(6,7,8)判定

    ————————————————————————————————————— if(!-[1,]){

       //判断IE6,7,8

      }
    —————————————————————————————————————

      它的原理实际上是利用了IE的bug。

      当我们写下一个数组 [1,].length

      在IE中 [1,].length -------> 2

      在非IE中 [1,].length -------> 1

      当我们试图打印[1,],相当于调用toString()方法

      在IE中 [1,] -------> "1,"

      在非IE中 [1,] -------> "1"

      当我们给它加上负号-[1,]

      在IE中 -[1,] -------> NaN

      在非IE中 -[1,] -------> -1

      当我们对它进行取反!-[1,]

      在IE中 !-[1,] -------> true

      在非IE中 !-[1,] -------> false

      这样我们就可以判断是否为IE浏览器了,这个bug一直到IE9之后才消失的。

      好了,这次的变态语法就先讲这么多,以后碰到更新鲜的再来给大家更新,拜拜。

  • 相关阅读:
    python Elementtree 生成带缩进格式的xml文件
    Tacotron2论文阅读笔记
    opencv3 7.3 重映射 仿射变换
    numpy.ndarray类型方法
    ubuntu安装百度输入法
    gitlab--cicd实践pytest和flask接口化
    django搭建完毕运行显示hello django
    django搭建
    服务器内存
    python安装第三方库aiohtpp,sanio失败,pip install multidict 失败问题
  • 原文地址:https://www.cnblogs.com/caominjie/p/10822937.html
Copyright © 2020-2023  润新知