乐趣区

关于javascript:前端装逼技巧-108-式一-打工人

你在拼多多到处找人砍价,他在滴滴打车求人助力,我在电子厂拧螺丝拧到凌晨,咱们都有光明的将来!早安,打工人!

楔子

  作为一名领有钢铁般意志的前端打工人,装逼是不可能的,这辈子都不可能装逼。如果真要装逼,那就大家一起装逼,毕竟前端要讲武德嘛,要耗子尾汁。遂决定写下前端装逼技巧 108 式,供诸君茶余饭后一乐,时不时秀个骚操作,为打工的生存削减一抹亮色。

  因作为打工人,工夫、精力有限,目前纲要只有约 50 式,还请诸君有好的装逼要点私信或者在评论区留言,也可在我的博客页面扫码增加微信,大家独特探讨装逼大计、独特迎接打工人的光明将来!

文章格调所限,援用材料局部,将在对应大节开端标出。

第一式:子曰,公欲装逼好,工具少不了

  • 代码太俊俏,carbon 来相救:把你的代码转换为精美图片进行分享(点击图片跳转)

  本文为便于代码复制,将奉行 不首先装逼 准则,尽量减少此装逼利器的应用。

第二式:console调试万金油,学会开车更上头

  console.log()在前端调试中的位置自不用赘述,其实一代车神也对其嗤之以鼻,不信诸君细看(如真有不解其意者,倡议发挥不耻下问的求知精力,问问你旁边的共事):

  是的,以上图片是由 console.log() 实现的,我没有骗你,贴出代码以证清白,为便于诸君控制台开车,此处咱们忘掉第一式:

// 在此揭示,为免于生成俊俏的锯齿背景图片,请留神空格的个数,并保障 console 面板的宽度。console.log(`%c                                                                            
                                                                            
                                                                            
                               %c FBI WARNING %c                                
                                                                            
                                                                            
%c        Federal Law provides severe civil and criminal penalties for        
        the unauthorized reproduction,distribution, or exhibition of        
         copyrighted motion pictures (Title 17, United States Code,         
        Sections 501 and 508). The Federal Bureau of Investigation          
         investigates allegations of criminal copyright infringement        
                 (Title 17, United States Code, Section 506).               
                                                                            
                                                                            
                                                                            
`,
'background: #000; font-size: 18px; font-family: monospace',
'background: #f33; font-size: 18px; font-family: monospace; color: #eee; text-shadow:0 0 1px #fff',
'background: #000; font-size: 18px; font-family: monospace',
'background: #000; font-size: 18px; font-family: monospace; color: #ddd; text-shadow:0 0 2px #fff'
)

  为什么会这样呢?想必你还记得其余语言中的 print()。占位符是print() 的专属吗?不,他们在 console.log() 中同样应用:

  • %s:字符串
  • %d:整数
  • %i:整数
  • %f:浮点数
  • %o:obj 对象(DOM)
  • %O:obj 对象
  • %c:CSS 款式

  console.log()能够通过以上这些特有的占位符进行信息的加工输入。是的,你可能曾经明确,下面代码的玄机就在四个%c,第一个创立神秘而性感的纯黑背景;第二个给“FBI WARNING”加上红色的背景;第三个复原纯黑的性感;第四个配上红色的文字,如此,小事已成。

  明确了以上原理,诸君就能够自由发挥,展现你们弱小的 css 实力了,甚至还能够输入 gif 背景图,在装逼的路上更上几层楼。不装了,我是 css 渣渣。

console.log(
  '%c 孤篷',
  'text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:5em'
  )

  那么,咱们是否能够超过度娘,在自家公司官网控制台实现精美的招聘文案投送呢?

  拓展:console对象都有哪些办法?

参考资料:小蝌蚪日记:通过 console.log 高仿 FBI Warning | Using the F12 Tools Console to View Errors and Status?redirectedfrom=MSDN)

第三式:芙蓉面,杨柳腰,无物比妖娆 —— 让你看清 UI 的轮廓

  • UI 轮廓哪里寻,outline属性来帮您。

    html * {outline: 1px solid red}

  • 解析与思考

    • 这里没有应用 border 的起因是 border 会减少元素的大小然而 outline 不会;
    • 通过这个技巧不仅能帮忙咱们在开发中迅速理解元素所在的地位,还能帮忙咱们不便地查看任意网站的布局;
    • 所有浏览器都反对 outline 属性;outline(轮廓)是绘制于元素四周的一条线,位于边框边缘的外围,可起到突出元素的作用;
    • 轮廓线不会占据空间,也不肯定是矩形(比方 2D 转换等)。
    • 去掉 Chrome 浏览器中输入框以及其它表单控件取得焦点时的带色彩边框

      input {outline: none;}
  • 通过一个开关实现任意网页开启敞开 outline

    • Chrome 右上角三个点⇒书签⇒书签管理器⇒右上角三个点⇒「增加新书签」;
    • 名称随便,粘贴以下代码到网址中;
    • 而后咱们就能够在任意网站上点击方才创立的书签,外部会判断是否存在调试的 style。存在的话就删除,不存在的话就增加,通过这种形式咱们就能很不便的通过这个技巧查看任意网页的布局了。

         javascript: (function() {var elements = document.body.getElementsByTagName('*');
            var items = [];
            for (var i = 0; i < elements.length; i++) {if (elements[i].innerHTML.indexOf('html * { outline: 1px solid red}') != -1) {items.push(elements[i]);
               }
            }
            if (items.length > 0) {for (var i = 0; i < items.length; i++) {items[i].innerHTML = '';
               }
            } else {
               document.body.innerHTML +=
                  '<style>html * {outline: 1px solid red}</style>';
            }
       })();

参考资料:很好用的 UI 调试技巧

第四式:角声寒,夜阑珊,又改需要。难,难,难!—— 类型转换助你不带脏字的骂产品、优雅的夸本人

  • (!(~+[])+{})[--[~+""][+[]]*[~+[]]+~~!+[]]+({}+[])[[~!+[]*~+[]]]:sb
  • ([][[]]+[])[+!![]]+([]+{})[!+[]+!![]]:nb
  • (+!![]*([]+{})+[]+{})[+[]]+([]+{})[!+[]+!![]]:Nb

图解:取类型转换失去的字符串里的字母进行拼凑(看懂了原理,其实咱们齐全能够尝试写的更简练一些)

插件:zhuangbility,一个能够逆向操作,输出文字,返回操作符的 npm 插件

第五式:a == 1 && a == 2 && a == 3,那你能够实现 a === 1 && a === 2 && a === 3 吗?

  • a == 1 && a == 2 && a == 3

      // 当然,你也能够把 count 作为属性放在 a 对象上
      let count = 1
      let a = {valueOf: function(){return count++}
      }
      console.log(a==1 && a==2 && a==3) // true
    • 对象在转换根本类型时,会调用该对象上 valueOftoString 这两个办法,该办法的返回值是转换为根本类型的后果
    • 具体调用以上哪个办法取决于内置的 toPrimitive 调用后果
  • a === 1 && a === 2 && a === 3
let count = 1;
Object.defineProperty(window, 'a', {get: function() {return count ++;}
});

console.log(a===1 && a===2 && a===3) // true

Object.defineProperty()办法会间接在一个对象上定义一个新属性,或者批改一个对象的现有属性,并返回此对象。同时,该 API 也是 Vue 2.x 数据绑定实现的外围,Vue 在 3.x 版本之后改用 Proxy 进行实现,本系列文章后续会进行简略探讨。

原理可参考:[[译] 在 JS 中,如何让 (a===1 && a===2 && a === 3)(严格相等) 的值为 true?](https://juejin.cn/post/684490… | 深入浅出 Object.defineProperty() | ECMAScript7 标准中的 ToPrimitive 形象操作

第六式:最近有点儿火的 Web Components 可能并不是小鲜肉

Web Components 原理:

  • html 很宽松,浏览器也能够辨认不规则、不非法标签(元素)(如<custom-label>Web Components</custom-label> 会展现 ”Web Components”。);
  • 自定义继承自 HTMLElement 的类,称为自定义元素的类;
  • 通过 window.customElements.defineAPI 定义和注册自定义元素,使得 不非法标签 (自定义元素)与自定义元素的类关联,实现 合法化
  • 通过模板标签 <template> 简化类的定义过程并增加款式;
  • 通过自定义元素的 attachShadow() 办法开启 Shadow DOM(这部分 DOM 默认与内部 DOM 隔离,外部任何代码都无奈影响内部),暗藏自定义元素的外部实现;
  • 增加事件监听、进行组件化封装等。

参考资料:Web Components 入门实例教程 - 阮一峰 | Window.customElements

第七式:Windows 环境变量设置其实能够很简略

  应用 Windows 零碎电脑进行开发的小伙伴兴许常常会碰到须要手动设置环境变量的状况,其实设置环境变量也能够很简略的通过命令行实现:


# 查看以后所有可用的环境变量
set
# 查看某个环境变量:查看 path 变量的值
set path
# 批改环境变量(留神:这里是笼罩)set 变量名 = 变量内容
# 设置为空
set 变量名 =
# 给变量追加内容(% 变量名 %; 代表以前的值)set 变量名 =% 变量名 %; 变量内容
# 将 C:\Go\bin\ 增加到 path 中
set path=%path%;C:\Go\bin\

参考资料:Windows 应用 cmd 命令行查看、批改、删除与增加环境变量

第八式:1.toFixed()1.0.toFixed()1..toFixed(),到底哪个写法是对的?

  在数字字面量中,1.xxxxx这样的语法是浮点数表示法。所以 1.toFixed() 这样的语法在 JavaScript 中会报错,这个谬误来自于浮点数的字面量解析过程,而不是“. 作为存取运算符”的处理过程。在 JavaScript 中,浮点数的小位数是能够为空的,因而“1.”和“1.0”将作为雷同的浮点数被解析进去。所以会呈现:

1. === 1; // true
1. === 1.0; // true
1 === 1.0; // true
1.; // 1
1.0; // 1

  既然“1.”示意的是浮点数,那么“1..toFixed”示意的就是该浮点数字面量的“.toFixed”属性。当是数字字面量时,可通过相似Number(1).toFixed() 创立根本包装类型(显示装箱),而后就能够进行属性和办法的增加、读取(或者可借助小括号把字面量括起来,通知浏览器引擎这是一个整体)。

  • 装箱:将根本数据类型转换为对应的援用类型的操作(装箱又分为隐式装箱和显式装箱);
  • 拆箱:把援用类型转换成根本数据类型。

  根本类型不能有属性和办法,当给它们增加属性的时候零碎会主动进行包装类并销毁:

var num = 1;
num.len = 2;
// 上一行代码会产生如下过程:// new Number(1).len =2; 
// delete len;
// 也就是会先增加 len 属性,以后语句执行完结后即销毁,所以下一行打印 num 还是 1,没有 len 属性。console.log(num, num.len);//1 undefined
var num = new Number(1);
num.len = 2;
console.log(num); // Number {1, len: 2}

参考拓展:谈谈 JavaScript 中装箱和拆箱

第九式:typeof 不靠谱,咱们又该如何判断类型?

  • typeof之殇:咱们应该都晓得,应用 typeof 能够精确判断除 null 以外的根本类型,以及 functionsymbol 类型;null 会被 typeof 判断为 object

    • 在 JavaScript 最后的实现中,JavaScript 中的值是由一个示意类型的标签和理论数据值示意的。对象的类型标签是 0。因为 null 代表的是空指针(大多数平台下值为 0x00),因而,null 的类型标签是 0,typeof null 也因而返回 “object”;
    • 在 ES 6 之前,typeof 总能保障对任何所给的操作数返回一个字符串。即使是没有申明的标识符,typeof 也能返回 ‘undefined’。应用 typeof 永远不会抛出谬误。但在退出了块级作用域的 let 和 const 之后,在其被申明之前对块中的 let 和 const 变量应用 typeof 会抛出一个 ReferenceError。块作用域变量在块的头部处于“暂存死区”,直至其被初始化,在这期间,拜访变量将会引发谬误。
  • 以前常常拿来判断数组的 instanceof 是怎么实现的:应用 a instanceof B 判断的是 a 是否为 B 的实例,即 a 的原型链上是否存在 B 构造函数(ES6 之后能够通过 Array.isArray() 来判断是否是数组)。

      // L 示意左表达式,R 示意右表达式
      const customInstanceof = (L, R) => {if (typeof L !== 'object') return false
        while (true) { 
          // 曾经遍历到了最顶端
          if (L === null) return false
          // 利用原型链进行判断
          if (R.prototype === L.__proto__) return true
          L = L.__proto__
        } 
      };
      customInstanceof([], Array) // true
  • constructor 为什么不是咱们的抉择?

    • constructor 属性是能够被批改的,会导致检测出的后果不正确;
    • 除了 undefinednull,其余类型的变量均能应用 constructor 判断出类型。

        let bool=true;
        bool.constructor==Boolean  //true
        let num1=1;
        num1.constructor==Number  //true
        let num2=new Number();
        num2.constructor==Number   //true
        // constructor 属性是能够被批改的
        num2.constructor = Object
        num2.constructor==Number   //false
        let str='hello world';
        str.constructor==String     //true
  • Object.prototype.toString 竟如此万能?

      Object.prototype.toString.call(123)
      //"[object Number]"
      Object.prototype.toString.call('str')
      //"[object String]"
      Object.prototype.toString.call(true)
      //"[object Boolean]"
      Object.prototype.toString.call({})
      //"[object Object]"
      Object.prototype.toString.call([])
      //"[object Array]"
      // 定义 getType 办法,用来判断类型
      getType = (obj) => {return Object.prototype.toString.call(obj).slice(8, -1)
      }
      getType(12n) // BigInt
      getType(Symbol()) // Symbol
      getType(() => {}) // Function
      getType() // Undefined
      getType(null) // Null
      getType(NaN) // Number

材料参考:typeof | The history of“typeof null”

第十式:十进制二进制互转,真的不必那么麻烦

  • 应用 NumberObject.toString(radix) 十进制转二进制:

    // 如有补齐位数的需要,可通过判断返回值的长度在后面加 0
    let num = 10;
    console.log(num.toString(2)); // 1010
  • 应用 parseInt(string, radix); 二进制转十进制:

    let num = 1010101;
    console.log(parseInt(num,2)); // 85
  • Tips:因为以上代码都应用 let 定义了 num 变量,除了刷新页面外,该如何在控制台别离执行呢?只需把代码放在一对花括号之间即可(块级作用域)。

第十一式:没有加减乘除,如何比拟正整数字符串的大小?

  在接手的局部我的项目中,存在须要前端拼接 Elasticsearch 查问语句的状况,好不容易会了点 Elasticsearch,却发现问题并没有那么简略:金额数量区间查问你通知我存储的是字符串?那岂不是会呈现 1<3000<5 的状况?天啦噜,不要逗我好吗?

  那么,在不改变 ES 的状况下,如何 通过正则表达式查问来实现正整数字符串大小的比拟 呢?间接说思路:数位更多或者从高位开始比,数值更大即是更大的数【一时间没想到更好的解法,有更好的解法欢送留言或者私信】。

// 通过正则表达式从字符串数组中筛选出大于某个数值的字符串类型数据
const filterStrNumberByRegExp = (num, arr) => {const strBaseNumber = num.toString();
  const arrBaseNumber = strBaseNumber.split('');
  const len = strBaseNumber.length;
  // 生成正则:数位更多或者从高位开始比,数值更大
  let strRegExp = `\\d{${len+1}}`;
  arrBaseNumber.map((item, index) => {
    // 这里因为有位数限度,'^' 和 '$' 不是必须的,能够去除
    strRegExp += `|${strBaseNumber.substring(index,-1) || '^'}[${+item + 1}-9]\\d{${len - index - 1}}$`
  });
  // 丢给 ES 进行查问时,貌似不可应用 \d(可用 [0-9] 代替)、结尾、结尾匹配等字符,下面四行可用上面正文内容替换
  //let strRegExp = `[0-9]{${len+1}}`;
  //arrBaseNumber.map((item, index) => {//  strRegExp += `|${strBaseNumber.substring(index,-1) || ''}[${+item + 1}-9][0-9]{${len - index - 1}}`
  //});
  const regExp = new RegExp(strRegExp);
  // 丢给 ES 进行正则查问时应用 strRegExp 后果
  console.log(regExp, strRegExp);
  return arr.filter(item => {
    // 小于等于判断的话,这里取反或者自行批改正则
    if(regExp.test(item)) return true;
  });
};
filterStrNumberByRegExp(386, ['12', '334', '556', '1122', '5546','234','388','387','1234','386','385']); // ["556", "1122", "5546", "388", "387", "1234"]

  具体 Elasticsearch 列表页搜寻公共办法实现能够查看我的这篇笔记。

第十二式:前端太寂寞?如何让页面和你谈话?—— TTS(Text To Speah)

  在我的项目中须要对 ajax 申请返回的音讯进行语音播报,str 为须要播报的信息(适应于错误信息语音提醒等场景):

// 语音播报
function voiceAnnouncements(str){
    // 百度语音合成:或者应用新版地址 https://tsn.baidu.com/text2audio
    var url = "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=5&text=" + encodeURI(str);
    var n = new Audio(url);
    n.src = url;
    n.play();};
voiceAnnouncements(`
秋名山上路人稀,常有车手较高下;现在车道仍旧在,不见当年老司机。司机车技今尚好,前端群里不寂寥;向天再借五百年,誓言各行领风骚。`);
// 尝试了一些换女声的形式,然而,都失败了。。。voiceAnnouncements(`
哇,代码写的真棒,你可真秀哇!`);
  • 参数解释:

    • lan:固定值 zh。语言选择, 目前只有中英文混合模式,填写固定值 zh
    • ie: 编码方式
    • spd:语速,取值 0 -9,默认为 5 中语速
    • text:合成的文本,应用 UTF- 8 编码。小于 512 个中文字或者英文数字。(文本在百度服务器内转换为 GBK 后,长度必须小于 1024 字节)
  • React Native Text-To-Speech library for Android and iOS
  • 用语音管制本人的网站 annyang:A tiny JavaScript Speech Recognition library that lets your users control your site with voice commands.annyang has no dependencies, weighs just 2 KB, and is free to use and modify under the MIT license。

第十三式:失焦事件与点击事件抵触怎么办?

  • 场景:

    • 下拉框中 blur 与 click 抵触;
    • 输入框 blur 与下方可点击浮沉 click 抵触:输出值时下方呈现浮层,输入框失去焦点时,浮层暗藏;点击浮层条目触发搜寻并暗藏浮层;
    • 问题:点击浮层时,因为失焦事件先触发,浮层暗藏逻辑执行,导致浮层的 onClick 事件逻辑无奈执行

// 点击弹窗条目进行搜寻
handleSearch = (activeSearch) => {console.log(activeSearch);
  this.setState({visible: false});
}

// 取得焦点,有值时展现弹窗
onFocus = () => {if (this.state.keyword) {this.setState({ visible: true});
  }
}

// 输出且有值时展现弹窗
onChange = (e) => {
  this.setState({
    keyword: e.target.value,
    visible: !!e.target.value
  })
}

// 失去焦点暗藏弹窗
onBlur = () => {if (this.state.keyword) {this.setState({ visible: false});
  }
}

render() {const { keyword, visible} = this.state;
  return (
    <div>
      <Input
        allowClear
        addonBefore={<Icon type="user" />}
        placeholder="反对 ID、名称、主邮箱、客户经理、专属账户、客户 ID、GroupID 搜寻"
        style={{ width: 460} }
        onFocus={this.onFocus}
        onChange={this.onChange}
        onBlur={this.onBlur}
      />
      {
        // 展现弹窗(点击条目实现搜寻)visible && keyword && <div className={styles.SearchSelect}>
          {
            showOptions.map(item => (
              <div
                onClick={() => this.handleSearch(item)}
                className={styles.item}
                key={item.key}
              >
                <div>
                  {item.label}:{keyword}
                </div>
              </div>
            ))
          }
        </div>
      }
    </div>
  );
}
  • 解决:

    • 办法一:给失焦事件设置提早触发

        onBlur = () => {if (this.state.keyword) {setTimeout(() => {this.setState({ visible: false});
            }, 300);
          }
        }
    • 办法二:应用 onMouseDown 代替 onClick

      • mousedown 事件:当鼠标指针挪动到元素上方,并按下鼠标按键时,会产生 mousedown 事件,所以它会先于失焦事件执行。
      • mouseup 事件:当在元素上放松鼠标按钮时,会产生 mouseup 事件。

第十四式:不必加减乘除如何做加法——位运算让你的代码更高效

  • JavaScript 位运算符

  位运算是基于二进制的,如何疾速取得二进制可参考第十式。

  • 不必加减乘除做加法

    function add(a,b) {
        let sum;
        let add1;
        while(b!=0) {
            // 异或
            sum = a^b;
            // 与 左移
            add1 = (a&b)<<1;
            a = sum;
            b = add1;
        }
        return a
    };
    add(1,2); // 3
  • JS 按位运算符的妙用:

    • 应用 & 运算符判断一个数的奇偶(只需记住 0 和 1 与 1 进行 & 运算的后果即可):

      • 偶数 & 1 = 0
      • 奇数 & 1 = 1
    • 应用 ~~,>>,<<,>>>,| 来取整:

      • ~~Math.PI:3(按位取反再取反)
      • Math.PI>>0Math.PI<<0Math.PI>>>0:3(按位左移或者右移 0 位,>>>不可用于正数)
      • Math.PI|0:3,按位异或
    • 应用 <<,>> 来计算乘除:

      • 整数左移 n 位相当于乘 2 的 n 次方;
      • 右移相当于除以 2 的 n 次方,再向下取整
    • 利用 ^ 来实现比拟两个数是否相等:!(a ^ b)
    • 应用 ^ 来实现值替换:参考第十五式
    • 应用 &,>>,| 来实现 rgb 值和 16 进制色彩值之间的转换

      • 16 进制色彩值转 RGB:

        function hexToRGB(hex){hex = hex.replace("#","0x");
          let r = hex >> 16;
          let g = hex >> 8 & 0xff;
          let b = hex & 0xff;
          return "rgb("+r+","+g+","+b+")";
        };
        hexToRGB('#cccccc'); // rgb(204,204,204)
      • RGB 转 16 进制色彩值:

        function RGBToHex(rgb){let rgbArr = rgb.split(/[^\d]+/);
          let color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3];
          return "#"+color.toString(16);
        };
        RGBToHex('rgb(204,204,204)'); // #cccccc

参考资料:JavaScript 位运算符

第十五式:无聊的脑筋急转弯,不借助第三个变量替换 a,b 两个变量值的 N 种办法

  • 办法一:加减

      a = a + b;
      b = a - b;
      a= a - b;
  • 办法二:位运算

      a ^= b;
      b ^= a;
      a ^= b;
  • 办法三:对象或者数组

      a = {a, b};
      b = a.a;
      a = a.b;
      // a = [a, b];
      // b = a[0];
      // a = a[1];
  • 办法四:ES 6 解构赋值

      [a, b] = [b, a]
  • 计划五:运算符优先级

      a = [b, b=a][0];

    参考资料:不借助第三个变量替换 a,b 两个变量值

第十六式:如何在浏览器以后页面关上并操作另一个 tab 页

  if (window.customeWindow) {window.customeWindow.close()
  }
  window.customeWindow = window.open()
  window.customeWindow.document.write('<p style="color:red"> 写点什么呢?<p>')
  window.customeWindow.document.write('<p style="color:#cccccc"> 想写什么就写什么。<p>')
  window.customeWindow.document.write('再追加点别的。')
  window.customeWindow.document.close() // 间断追加输出完结
  window.customeWindow.document.write('哈哈,当初页面上就只有我了!')
  window.customeWindow.document.write('<p style="color:red"> 不,还有我!<p>')

参考资料:BRAFT EDITOR 富文本编辑器预览

第十七式:产品说要依照中文拼音程序排序?

  • 应用 stringObject.localeCompare(target) 办法实现中文依照拼音程序排序
var array = ["上海", "北京", "杭州", "广东", "深圳", "西安"];
// localeCompare() 办法返回一个数字来批示一个参考字符串是否在排序程序后面或之后或与给定字符串雷同。array = array.sort((item1, item2) => item1.localeCompare(item2));
// ["北京", "广东", "杭州", "上海", "深圳", "西安"]

参考资料:String.prototype.localeCompare()

  • 一个对象数组依照另一个数组排序
sortFunc = (propName, referArr) => (prev, next) => 
referArr.indexOf(prev[propName]) - referArr.indexOf(next[propName])
// 依照年龄 age 的程序给 person 排序
const age = [33, 11, 55, 22, 66];
const person = [{age: 55, weight: 50},
 {age: 22, weight: 42},
 {age: 11, weight: 15},
 {age: 66, weight: 56},
 {age: 33, weight: 68}]
person.sort(sortFunc('age', age));
// 后果:// [//  {"age": 33,"weight": 68},
//  {"age": 11,"weight": 15},
//  {"age": 55,"weight": 50},
//  {"age": 22,"weight": 42},
//  {"age": 66,"weight": 56}
// ]

第十八式:这段代码为什么会报错,说好的分号能够省略呢?

  console.log(123)
  [12,2].filter(item => item > 3)
  // Uncaught TypeError: Cannot read property '2' of undefined
  // at <anonymous>:2:1
  • 分号推断:编译原理里的 分号推断,作用是在编程的时候,让程序员省略掉不必要的分号;
  • JavaScript 有着 主动分号插入的机制(Automatic Semicolon Insertion),简称 ASI(ASI 只是示意编译器正确理解了程序员的用意,并没有真的插入分号);
  • 浏览器引擎的 Parser(负责将 JS 源码转换为 AST)总是优先将换行符前后的符号流当作一条语句解析(带换行的多行正文与换行符是等效的);
  • 所以在 Parser 眼里,以上代码是这样的:

    • console.log(123)[12,2].filter(item => item > 3)console.log(123)没有返回值,既undefined
    • [12,2]中的方括号被视为读取 console.log(123) 返回值中的属性2,相似于依据下标取数组中的元素;
    • 为什么是取属性 2 呢,因为 12,2 是个逗号表达式,表达式的值是最左边的“2”,如此以来,下面的报错信息就很好了解了。
  • 不能省略的分号:

    • for 循环头部的分号
    • 作为空语句存在的分号
    • [、(、结尾的语句之前的分号

    材料参考:备胎的自我涵养——趣谈 JavaScript 中的 ASI (Automatic Semicolon Insertion)

本文首发于集体博客,欢送斧正和 star。

退出移动版