久经沙场的前辈们,写了有数代码,踩了有数的坑。但有些坑,可能一辈子也踩不到摸不着,因为基本不会产生在业务代码里~~

1

Function.prototype 居然是个函数类型。而自定义函数的原型却是对象类型。

typeof Function.prototype === 'function';  // trueconst People() {}typeof People.prototype === 'object';      // true

所以咱们设置空函数能够这么做:

// Good const noop = Function.prototype;// Badconst noop = () => {};

2

一个变量真的会不等于本身吗?

const x = NaN;x !== x  // true

这是目前为止js语言中惟一的一个不等于本人的数据。为什么?因为NaN代表的是一个范畴,而不是一个具体的数值。
在晚期的 isNaN() 函数中,即便传入字符串,也会返回true,这个问题曾经在es6中修复。

isNaN('abc');       // trueNumber.isNaN('abc') // false

所以如果您想兼容旧浏览器,用 x !== x 来判断是不是NaN,是一个不错的计划。

3

构造函数如果return了新的数据

// 不返回const People() {}const people = new People();   // People {}// 返回数字const People() {  return 1;}const people = new People();   // People {}// 返回新对象const Animal() {  return {    hello: 'world',  };}const animal = new Animal();  // { hello: 'world' }

在实例化构造函数时,返回非对象类型将不失效

4

.call.call 到底在为谁疯狂打call?

function fn1() {  console.log(1);}function fn2() {  console.log(2);}fn1.call.call(fn2); // 2

所以 fn1.call.call(fn2) 等效于 fn2.call(undefined)。而且无论您加多少个 .call,成果也是一样的。

5

实例后的对象也能再次实例吗?

function People() {}const lili = new People();            // People {}const lucy = new tom.constructor();   // People {}

因为lili的原型链指向了People的原型,所以通过向上寻找个性,最终在 Peopel.prototype 上找到了结构器即 People本身

6

setTimeout 嵌套会产生什么奇怪的事件?

console.log(0, Date.now());setTimeout(() => {  console.log(1, Date.now());  setTimeout(() => {    console.log(2, Date.now());    setTimeout(() => {      console.log(3, Date.now());      setTimeout(() => {        console.log(4, Date.now());        setTimeout(() => {          console.log(5, Date.now());          setTimeout(() => {            console.log(6, Date.now());          });        });      });    });  });});

在0-4层,setTimeout的距离是1ms,而到第5层时,距离至多是4ms。

7

es6函数带默认参数时将生成申明作用域

var x = 10;function fn(x = 2, y = function () { return x + 1 }) {  var x = 5;  return y();}fn();   // 3

8

函数表达式(非函数申明)中的函数名不可笼罩

const c = function CC() {  CC = 123;  return CC;};c(); // Function

当然,如果设置var CC = 123,加申明关键词是能够笼罩的。

9

严格模式下,函数的this是undefined而不是Window

// 非严格function fn1() {  return this;}fn1(); // Window// 严格function fn2() {  'use strict';  return this;}fn2(); // undefined

对于模块化的通过webpack打包的代码,根本都是严格模式的代码。

10

取整操作也能够用按位操作

var x = 1.23 | 0;  // 1

因为按位操作只反对32位的整型,所以小数点局部全副都被摈弃

11

indexOf() 不须要再比拟数字

const arr = [1, 2, 3];// 存在,等效于 > -1if (~arr.indexOf(1)) {}// 不存在,等效于 === -1!~arr.indexOf(1);

按位操作效率高点,代码也简洁一些。也能够应用es6的includes()。但写开源库须要思考兼容性的道友还是用indexOf比拟好

12

getter/setter 也能够动静设置吗?

class Hello {  _name = 'lucy';   getName() {    return this._name;  }    // 动态的getter  get id() {    return 1;  }}const hel = new Hello();hel.name;       // undefinedhel.getName();  // lucy// 动静的getterHello.prototype.__defineGetter__('name', function() {  return this._name;});Hello.prototype.__defineSetter__('name', function(value) {  this._name = value;});hel.name;       // lucyhel.getName();  // lucyhel.name = 'jimi';hel.name;       // jimihel.getName();  // jimi

13

0.3 - 0.2 !== 0.1  // true

14

class语法糖到底是怎么继承的?

function Super() {  this.a = 1;}function Child() {  // 属性继承  Super.call(this);  this.b = 2;}// 原型继承Child.prototype = new Super();const child = new Child();child.a;  // 1

正式代码的原型继承,不会间接实例父类,而是实例一个空函数,防止反复申明动静属性

const extends = (Child, Super) => {  const fn = function () {};    fn.prototype = Super.prototype;  Child.prototype = new fn();  Child.prototype.constructor = Child;};

15

脑袋空了,收集中,可遇不可求。。。