一些常见的高级函数

91 阅读2分钟

这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

除了函数相关的基础知识外,掌握一些高级函数并应用起来,不仅能让JS代码看起来更为精简,还可以提升性能。很多“高级函数”的实现其实并不复杂,数十行代码便可搞定,但重要的是能真正理解它们的原理,在实际中适时地应用。

安全的类型检测

在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。如:

console.log(Object.prototype.toStrig.call(value)); // "[object Array]"

所以,使用 toString() 能保证返回一致的值。更安全的类型检测可以创建如下函数:

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

function isRegExp(value) {
    return Object.prototype.toString.call(value) == "[object RegEXP]";
}

作用域安全的构造函数

构造函数是一个使用 new 操作符调用的函数。

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

var person = new Person("nickname", 20, "teacher");

看似没有问题,但是如果没有使用 new 操作符调用该构造函数时,该 this 对象是在运行时绑定的,直接调用 Person(),this 会映射到 window 上。

解决方法:创建一个作用域安全的构造函数。在进行任何更改前,先确认 this 对象是正确类型的实例,如果不是,创建新的实例并返回。

function Person(name, age, job) {
    if (this instanceof Person) {
        this.name = name;
        this.age = age;
        this.job = job;
    } else {
        return new Person(name, age, job);
    }
}

惰性载入函数

惰性载入表示函数执行的分支仅会发生一次。惰性载入方式:

  • 函数被调用时再处理函数。在第一次调用时,用另外一个按合适方式执行的函数覆盖该函数。如:

    function createXHR() {
        if (typeof XMLHttpRequest != "undefined") {
            createXHR = function() {
                return new XMLHttpRequest();
            };
        } else if (typeof ActiveXObject != "undefined") {
            createXHR = function() {
                ...dosomething
            };
        } else {
            createXHR = function() {
                throw new Error("error");
            };
        }
    
        return createXHR();
    }
    

    if 语句的每一个分支都会为 createXHR 变量赋值,覆盖原有的函数。

  • 在声明函数时指定适合的函数。

    var createXHR = (function createXHR() {
        if (typeof XMLHttpRequest != "undefined") {
            return function() {
                return new XMLHttpRequest();
            };
        } else if (typeof ActiveXObject != "undefined") {
            return function() {
                ...dosomething
            };
        } else {
            return function() {
                throw new Error("error");
            };
        }
    })();
    

    创建一个匿名、自执行的函数,确定使用哪一个函数实现。

惰性载入函数只在执行分支代码时牺牲一点儿性能。