JS红皮书解读之高级函数

一、安全的类型检测
typeof、instanceof检测某个对象是原生对象还是自定义对象,有时会出错
可采用Object原生的toString()方法来检测:

(1)检测原生数组

    function isArray(value) {
      return Object.prototype.toString.call(value)==='[object Array]'
    }

(2)检测原生函数

    function isFunction(value) {
      return Object.prototype.toString.call(value)==='[object Function]'
    }

(3)检测原生正则表达式

    function isRegExp(value) {
      return Object.prototype.toString.call(value)==='[object RegExp]'
    }

原理:
任何值调用Object原生的toString方法,都会返回一个[object NativeConstructorName]格式的字符串。
而Array、Object、Function这些类的内部都是一个[[Class]]属性,这个属性就指定了NativeConstructorName的具体的名字,如 Object、Array、RegExp、Function

从而能判断是否是原生JS对象

二、作用域安全的构造函数
注意:构造函数就是用new调用的函数

    function Person(name,age,sex){
      this.name=name
      this.age=age
      this.sex=sex
    }

new后就是新创建对象,this指的就是这个新对象(新实例)

    let personA=new Person("a",'18','man')
    console.log(personA,window.name,window.age,window.sex) //{age:"18",name:"a",sex:"man"}

不用new的后果就是window来调用Person构造函数,导致Person内部的this指的是window,而name、age、sex也都是window属性了。

    let personB=Person("b",'22','woman')
    console.log(personB,window.name,window.age,window.sex) //undefined "b" "22" "woman"

因此,在调用构造函数时,需要判断其作用域


解决方法:先确认this对象是正确类型的实例,若不是,则创建新的实例并返回:

    function Person(name,age,sex){
      // instanceof xxx的实例
      if(this instanceof Person){
        this.name=name
        this.age=age
        this.sex=sex
      }else{
        return new Person(name,age,sex)
      }
    } 

缺陷:使用构造函数的窃取模式 xxx.call(this.xxx) 且不用原型链,会破坏该继承

    function Father(age){
      if(this instanceof Father){
        this.age=age
      }else{
        return new Father(age)
      }
    }

    function Child(sex) {
      //因为Child不是Father的一个实例(this instanceof Father是false),
      // 所以是新创建的Father对象
      //新创建的对象 不等于 Child函数本身
      Father.call(this,18)
      //this指的Child
      //如果Father没有判断(this instanceof Father),
      //则Father里面this.age的this指的就是Child了
      this.sex=sex
    }

    let childA=new Child('man')
    console.log(childA.age) //undefined

简而言之就是Child在调用Father的属性时,新创建的Father实例,导致this不是Child自身的this。

解决:
使用原型链

    ...
    ...
    ...
    //让Child的原型等于Father的实例
    Child.prototype=new Father()
    let childA=new Child('man')
    console.log(childA.age) //18

三、惰性载入(优化项目)
让if语句不必每次都执行,即惰性载入
为啥?因为有if语句会比没有if语句慢一些

    function  createFamily(number){
      if(number===1){
       //xxxx1
      }else{
        if(number===2){
          //xxxx2
        }else{
          //xxxx3
        }
      }
    }

第一种优化:

    function  createFamily(number){
      if(number===1){
        createFamily=function () {
          //xxxx1
        }
      }else{
        if(number===2){
          createFamily=function () {
            //xxxx2
          }
        }else{
          createFamily=function () {
            //xxxx3
          }
        }
      }
    }

第二种优化:

    let createFamily=(function(number) {
      if(number===1){
        return function () {
          //xxxx1
        }
      }else{
        if(number===2){
          return function () {
            //xxxx2
          }
        }else{
          return function () {
            //xxxx3
          }
        }
      }
    //  这里是number的具体值
    })(number)

注意:仅用于第一次判断走哪边,不适用于来回切换判断条件!下次调用就直接不判断,走那一边了。这个可用于项目代码优化。

(完)

你可能感兴趣的:(JS红皮书解读之高级函数)