zoukankan      html  css  js  c++  java
  • 那些短小精悍的&奇葩的&令人感到惊讶的JavaScript代码----更新中

    自学习前端以来,陆陆续续遇见很多短小令人惊讶的js代码,固有了专门开一片日记来记录这些代码的想法。借此提高写代码的姿势和深度理解JavaScript。

    1.JavaScript中 (a 1 && a 2 && a==3) 可能为 true 吗?

    来自Stack Overflow的一个问题:链接

    国外面试题,Nothing is impossible.

    解决方案1:
    自定义 toString(或者 valueOf)方法,每次调用改变一次返回值,从而满足判断条件。

    const a = {
      i: 1,
      toString: function () {
        return a.i++;
      }
    }
    
    if(a == 1 && a == 2 && a == 3) {
      console.log('Hello World!');
    }
    

    tostring()属于Object对象,当使用 == 时,如果两个参数的类型不一样,那么 JS 会尝试将其中一个的类型转换为和另一个相同。在这里左边对象,右边数字的情况下,会首先尝试调用 valueOf(如果可以调用的话)来将对象转换为数字,如果失败,再调用 toString。

    第二个方法,有点像障眼法,=-=:

    var aᅠ = 1;
    var a = 2;
    var ᅠa = 3;
    if(aᅠ==1 && a== 2 &&ᅠa==3) {
        console.log("Why hello there!")
    }
    

    注意在if语句(我从你的问题中复制)怪异的间距。 这是半角Hangul(即那些不熟悉的韩语),它是一个Unicode空格字符,不被ECMA脚本解释为空格字符 - 这意味着它是一个标识符的有效字符。 因此,有三个完全不同的变量,一个是在一个之后的Hangul,另一个是前一个,最后一个只有一个。 为了便于阅读,用_替换空格,相同的代码如下所示:

    var a_ = 1;
    var a = 2;
    var _a = 3;
    if(a_==1 && a== 2 &&_a==3) {
        console.log("Why hello there!")
    }
    

    哈哈哈,我一般还通过切换半角全角符号方便在Markdown里做段落的空格处理。

    还有一种解决方法就是js的with语句,把对象的作用域的范围明确出来(听说with语句缓慢)

    var i = 0;
    
    with({
      get a() {
        return ++i;
      }
    }) {
      if (a == 1 && a == 2 && a == 3)
        console.log("wohoo");
    }
    

    还有很多办法来解决这个,感兴趣自己可探究。

    2.JavaScript合并数组

    第一种方法

    ES6之前,

    // `b` onto `a`:
    a.push.apply( a, b );
    a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
    
    // or `a` into `b`:
    b.unshift.apply( b, a );
    
    b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
    

    看apply的文档;

    第二个参数:argsArray 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或
    undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。

    所以

    let a = [1,2,3],b=[4,5,6];
    a.push.apply(a,b);
    

    实质上会将b中三个元素4,5,6当作a.push的参数,这里的a不是apply左边的a,而是传给apply的第一个参数。前面的a只是为了使用push方法,这里的fun函数就是push,换句话说,apply会将第二个类数组参数拆分成一个个单独项。
    而与之对应的有个call方法。

    let a = [1,2,3];
    a.push.call(a,4,5,6);
    

    虽然支持超过2个参数,但需要将参数都列出来,在数组操作上比apply要弱上许多。

    第二种方法

    ES6后有了扩展运算符很方便

    let a = [1,2,3],b=[4,5,6];
    a.push(...b) // 6
    a // [1, 2, 3, 4, 5, 6]
    

    第三种方法

    用reduce函数,文档:

    array.reduce(function(total, currentValue, currentIndex, arr), initialValue)这里写图片描述

    合并操作:

    // `b` onto `a`:
    a = b.reduce( function(coll,item){
        coll.push( item );
        return coll;
    }, a );
    a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
    
    // or `a` into `b`:
    b = a.reduceRight( function(coll,item){
        coll.unshift( item );
        return coll;
    }, b );
    
    b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
    

    3.万能变量类型检测

    1.首先想到的肯定是用typeof 检测
    2.利用toString()检测:

    通过toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。

    如果在控制台输入:
    var a = '111'
    Object.prototype.toString(a)
    返回:"[object Object]"
    Object.prototype.toString(a) 中toString 的 this 是 Object.prototype,会返回[Object ],a 是 toString 的参数。 Object.prototype.toString.call(a) 中toString 的 this 是 a,没有参数。

    变量检测:

    var toString = Object.prototype.toString;
    
    toString.call(new Date); // [object Date]
    toString.call(new String); // [object String]
    toString.call(Math); // [object Math]
    
    //Since JavaScript 1.8.5
    toString.call(undefined); // [object Undefined]
    toString.call(null); // [object Null]
    

    很强大吧,undefined和null都能检测出来。。

  • 相关阅读:
    设计模式之结构型外观模式
    设计模式之结构型装饰者模式
    设计模式之结构型组合模式
    设计模式之创建型建造者模式
    设计模式之创建型原型模式
    设计模式之创建型单例模式
    设计模式之创建型抽象工厂模式
    设计模式之创建型工厂模式
    设计模式之创建型简单工厂模式
    找出数组出现最多的元素,并返回出现的下标
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/8372392.html
Copyright © 2011-2022 走看看