JS程序设计高级技巧

一、高级函数

  1. 安全类型检测

    Object.protitype.toString.call(value)
  2. 作用域安全的构造函数

    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 Teacher (name, age, job, salary) {
        // this指向非Peroson 返回新的实例,构造函数中的this属性并未增长
        Person.call(this, name, age, job); 
        this.salary = salary;
    }
    // 解决这个问题的方法是,Teacher.prototype = new Person(),此时一个Teacher实例也是一个Person实例
  3. 惰性载入函数
    在函数被调用的时候再处理函数,在第一次调用的过程中,该函数会被覆盖为另一个按合适方式执行的函数

    function createXHR () {
        if (typeof XMLHttpRequest != 'undefined) {
            createXHR  = function () {
                return new XMLHttpRequest ();
            }
        } else if (typeof ActiveXObject != 'undefined') {
            createXHR = function () {
                if (typeof arguments.callee.activeString != 'string') {
                    //...
                }
            }
        } else {
            createXHR  = function () {
                // ...
            }
        }
        return createXHR();
    }

    在声明的时候就指定适当的函数,利用匿名函数自运行,return一个合适的函数

  4. 函数绑定
    一个简单的bind函数

    function bind(fn, context){
        return function() {
            return fn.apply(context, arguments)
        }
    }
  5. 函数柯里化
    函数的柯里化的基本方法和函数绑定是一样的,使用一个闭包返回一个函数,区别是,当函数被调用时,还需要传递一些参数
    柯里化函数动态创建步骤:调用另一个函数并为它传入要柯里化的函数和必要参数

    function curry(fn){
        var args = Array.prototype.slice.call(arguments, 1);
        return function () {
            var innerArgs = Array.prototype.slice.call(arguments);
            var finalArgs = args.concat(innerArgs);
            return fn.apply(null, finalArgs)
        }
    }
  6. es5中的防篡改对象
    不可扩展对象

    Objcect.preventExtensions(obj)   // 设置对象属性是否可以扩展
    Objcect.isExtensible(obj)         // 返回值为bool值,true即该对象可以扩展,false为不可扩展

    密封的对象
    密封对象不可扩展,而且已有成员的[ [ Configurable ] ]特性将被设置为false,这就意味着不能删除属性和方法

    Object.seal(obj)     // 设置对象是否是密封
    Object.isSealed    // 返回值为bool值,true即该对象已经密封,false为没有密封

    冻结对象
    冻结的对象既不可以扩展,又是密封的

    Object.freeze(obj)         // 设置对象是否冻结
    Objcet.isForzen(obj)    // 返回值为bool值,true即该对象已经冻结,false为没有冻结
  7. 高级定时器
    除了主Javascript执行进程外,还有一个需要在进程下次一空闲的时执行的代码队列。随着页面在其生命周期中的推移,代码会按照执行顺序添加到队列。
    关于定时器要记住的最重要的事情是:指定的时间间隔表示何时将定时器的代码添加到队列,而不是何时实际执行代码。
    a.重复的定时器

    使用setInterval()创建的定时器确保了定时器代码规则地插入队列中,这个方式的问题在于定时器代码可能在代码再次被添加到队列之前还没有完成执行,结果导致定时器代码连续运行好几次,而之间没有任何停顿,javascript引擎在使用setInterval时,仅当没有该定时器的代码是才将定时器的代码添加到队列中,但是这样会导致1、某些间隔时间被跳过。

    b.多个定时器之间的执行间隔会比预期的小

    // 解决办法
    setTimeout(function () {
        //处理中
        setTimeout(arguments.callee, interval)
    }, interval)
  8. 数组分块

    function chunk(array, process, context) {
        setTimeout( function() {
            var Item = array.shift();
            process(item)
            if (array.length > 0) {
                setTimeout(arguments.callee, 100)
            }
        }, 100)
    }
  9. 函数节流

    var processor = {
        timeoutId = null,
        // 实际进行处理的方法
        performProcessing: function() {
        // 实际执行的代码
    },
    // 初始处理调用的方法
    process: function () {
        clearTimeout(this.timeouId);
        var that = this;
        this.timeoutId = setTimeout(function () {
            that.performProcessing();
        }, 100)
        }
    }

你可能感兴趣的:(javascript)