js常用技巧总结

  1. 判断对象的数据类型
    使用 Object.prototype.toString 配合闭包,通过传入不同的判断类型来返回不同的判断函数

    1
    2
    3
    4

    const isType = type => target => `[object ${type}]` === Object.prototype.toString.call(target)
    const isArray = isType('Array')
    console.log(isArray([]))
  2. new的实现原理是什么?

new 的实现原理:

  1. 创建一个空对象,构造函数中的this指向这个空对象
  2. 这个新对象被执行 [[原型]] 连接
  3. 执行构造函数方法,属性和方法被添加到this引用的对象中
  4. 如果构造函数中没有返回其它对象,那么返回this,即创建的这个的新对象,否则,返回构造函数中返回的对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function _new() {
//创建一个空对象
let target = {}
// 第一个参数是构造函数
let [constructor, ...args] = [...arguments]
// 执行[[原型]]链接;target是constructor的实例
traget.__proto__ = constructor.prototype
// 执行狗仔函数,将属性和方法添加到创建的空对象上
let result = constructor.apply(target, args)
if (result && (typeof(result) == 'object' || typeof(result) == 'function')) {
// 如果构造函数执行的结构返回的是一个对象,那么返回这个对象
return result
}
// 如果构造函数返回的不是一个对象,返回创建的新对象
return target
}
  1. 如何正确判断this的指向?
  • 如果用一句话说明 this 的指向,那么即是: 谁调用它,this 就指向谁。
  • this 的指向可以按照以下顺序判断:
    • 全局环境中的 this
      浏览器环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象 window;
      node 环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this 都是空对象 {};
  • 是否是 new 绑定

    如果是 new 绑定,并且构造函数中没有返回 function 或者是 object,那么 this 指向这个新对象。如下:构造函数返回值不是 function 或 object。new Super() 返回的是 this 对象。
    构造函数返回值是 function 或 object,new Super()是返回的是Super种返回的对象。

    1
    2
    3
    4
    5
    function Super(age) {
    this.age = age
    }
    let instance = new Super('22')
    console.log(instance.age) //22
  • 函数是否通过 call,apply 调用,或者使用了 bind 绑定,如果是,那么this绑定的就是指定的对象【归结为显式绑定】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function info() {
    console.log(this.age)
    }
    var person = {
    age:20,
    info
    }
    var age = 28;
    var info = person.info
    info.call(person) //20
    info.apply(person)//20
    info.bind(person)()//20

如果 call,apply 或者 bind 传入的第一个参数值是 undefined 或者 null,严格模式下 this 的值为传入的值 null /undefined。非严格模式下,实际应用的默认绑定规则,this 指向全局对象(node环境为global,浏览器环境为window)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function info() {
// node环境中:非严格模式global,严格模式为null
// 浏览器环境中:非严格模式window,严格模式为null
console.log(this)
console.log(this.age)
}
var person = {
age:20,
info
}
var age = 28;
var info = person.info;
info.call(null)
// 严格模式抛出错误
// 非严格模式,node输出indefined,全局age不会挂在global上
// 非严格模式,浏览器环境下输出28,全局的age会挂在window上
  • 隐式绑定,函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。典型的隐式调用为: xxx.fn()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function info() {
    console.log(this.age)
    }
    var person = {
    age:20,
    info
    }
    var age = 28;
    person.info() //20