JavaScript MVC 进修笔记(四)类的运用(下)

掌握“类”库的作用域

在类和实例中都增加proxy函数,能够在事宜处置惩罚顺序以外处置惩罚函数的时刻对峙类的作用域。下面是不必proxy的方法:

var Class = function(parent){
    var klass = function(){
        this.init.apply(this, arguments);
    };

    klass.prototype.init = function(){};
    klass.fn = klass.prototype;

    // 增加一个proxy 函数
    klass.proxy = function(func){
        var self = this;
        return(function(){
            return func.apply(self, arguments);
        });
    }

    // 在实例中也增加这个函数
    klass.fn.proxy = klass.proxy;
    return klass;
};

下面是用proxy()函数来包装函数,以确保它们在准确的作用域中被挪用:

var Button = new Class;
    Button.include({
    init: function(element){
        this.element = jQuery(element);

        // 代理了这个click 函数
        this.element.click(this.proxy(this.click));
    },
    click: function(){ /* ... */ }
});

假如没有运用proxyclick()的回调包装起来,它就会基于高低文this.element来挪用,而不是Button,这会形成种种题目。在新版本的JavaScript——ECMAScript 5(ES5)——中一样加入了bind()函数用以掌握挪用的作用域。bind()基于函数举行挪用的,用来确保函数是在指定的this值地点的高低文中挪用的。比方:

Button.include({
    init: function(element){
        this.element = jQuery(element);
        // 绑定这个click 函数
        this.element.click(this.click.bind(this));
    },
    click: function(){ /* ... */ }
});

这个例子和proxy()函数是等价的,它能确保click() 函数基于准确的高低文举行挪用。老版本的浏览器不支撑bind(),但能够手动完成它,兼容性也不错,直接扩大相干对象的原型,如许就能够像在ES5 中运用bind(),在恣意浏览器中挪用它。下面是一段完成了bind() 函数的代码:

if (!Function.prototype.bind) {
    Function.prototype.bind = function (obj) {
        var slice = [].slice,
        args = slice.call(arguments, 1),
        self = this,
        nop = function () {},
        bound = function () {
        return self.apply( this instanceof nop ? this : (obj || {}),
            args.concat(slice.call(arguments)));
        };

        nop.prototype = self.prototype;
        bound.prototype = new nop();
        return bound;
    };
}

假如浏览器原生不支撑bind(),则仅仅重写了Function 的原型。当代浏览器则能够继续运用内置的完成。

关于数组来讲这类“打补丁”式的做法异常有效,由于在新版本的JavaScript 中,数组增加了许多新的特征。能够运用es5-shi项目,它涵盖了ES5 中新增的尽量多的特征。

增加私有函数

现在上面为“类”库增加的属性都是“公然的”,能够被随时修正。关于给“类”增加私有属性,JavaScript支撑不可变属性,但在主流浏览器中并未完成,没方法直接运用这个特征。能够运用JavaScript 匿名函数来建立私有作用域,这些私有作用域只能在内部接见:

var Person = function(){};

(function(){
    var findById = function(){ /* ... */ };
    Person.find = function(id){

    if (typeof id == "integer")
        return findById(id);
    };
})();

上面的代码将类的属性都包装进一个匿名函数中,然后建立了局部变量(findById),这些局部变量只能在当前作用域中被接见到。Person变量是在全局作用域中定义的,能够在任何地方都能接见到。定义变量的时刻不要丢掉var运算符,假如丢掉var就会建立全局变量。假如须要定义全局变量,能够在全局作用域中定义,或许定义为window的属性:

(function(exports){
    var foo = "bar";

    // 将变量暴露出去
    exports.foo = foo;
})(window);

assertEqual(foo, "bar");

“类”库

jQuery 自身并不支撑类,但经由过程插件的体式格局能够随意马虎引入类的支撑,比方HJS。HJS 许可经由过程给$.Class.create传入一组属性来定义类:

var Person = $.Class.create({

    // 组织函数
    initialize: function(name) {
        this.name = name;
    }
});

能够在建立类的时刻传入父类作为参数,如许就完成了类的继续:

var Student = $.Class.create(Person, {
    price: function() { /* ... */ }
});

var alex = new Student("Alex");
alex.pay();

能够直接给类挂载属性:

Person.find = function(id){ /* ... */ };

HJS 的API 中一样包括一些东西函数,比方clone() 和equal() :

var alex = new Student("Alex");
var bill = alex.clone();
assert( alex.equal(bill) );

另有 Spine 一样完成了类,经由过程直接在页面中引入spine.js(http://maccman.github.com/spine/spine.js)来运用它:

    <script src="http://maccman.github.com/spine/spine.js"> </script>
    <script>
        var Person = Spine.Class.create();

        Person.extend({
            find: function() { /* ... */ }
        });

        Person.include({
            init: function(atts){
            this.attributes = atts || {};
            }
        });

        var person = Person.init();
    </script>

jQuery 的作者John Resig 在他的博客中写过一篇文章:特地解说怎样完成典范的类继续

公然纪录进修JS MVC,不知道能对峙多久= =。以《基于MVC的JavaScript web富运用开辟》为重要进修材料。类的部份终究看完了,再逐步消化。JS真是博大精深!

    原文作者:JingDing
    原文地址: https://segmentfault.com/a/1190000002534590
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞