JavaScript MVC 进修笔记(二)类的运用(上)

公然纪录进修JS MVC,不知道能对峙多久= =。以《基于MVC的JavaScript web富运用开辟》为重要进修材料。

JavaScript类的内容很多,我脑容量太小,分两次进修

JavaScript的类

JavaScript是基于原型的言语,没有包括内置的类,然则经由过程JavaScript能够轻易地模仿出典范的类。JavaScript中有组织函数和 new 运算符。组织函数用来给实例对象初始化属性和值。任何JavaScript函数都能够用做组织函数,组织函数必需运用new 运算符作为前缀来建立新的实例。

new 运算符改变了函数的实行上下文,同时改变了return 语句的行动。实际上,运用new和组织函数和传统的完成了类的言语中的运用要领是很相似的:

var Person = function(name) {
  this.name = name;
};

// 实例化一个Person
var alice = new Person('alice');

// 搜检这个实例
assert( alice instanceof Person );

组织函数的定名一般运用驼峰定名法,首字母大写,以此和一般的函数辨别开来,这是一种习惯用法。

不要省略new前缀的体式格局来挪用组织函数:

// 不要这么做!
Person('bob'); //=> undefined

这个函数只会返回undefined,而且实行上下文是window(全局)对象,你无意间建立了一个全局变量name。挪用组织函数时不要丢掉new关键字。

当运用new关键字来挪用组织函数时,实行上下文从全局对象(window)变成一个空的上下文,这个上下文代表了新天生的实例。因而,this关键字指向当前建立的实例。只管明白起来有些绕,实际上其他言语内置类机制的完成也是云云。默许情况下,假如组织函数中没有返回任何内容,就会返回this——当前的上下文。要不然就返回恣意非原始范例的值。

建立本身的类模仿库

var Class = function(){

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

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

    return klass;
};

var Person = new Class;

Person.prototype.init = function(){
  // 基于Person 的实例做初始化
};

// 用法:
var person = new Person;

因为 JavaScript 2 范例从未被完成过,class 一向都是保留字。最罕见的做法是将变量名 class 改成 _classklass

给类增加函数

在JavaScript 中,在组织函数中给类增加函数和给对象增加属性是一样的:

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

要想给组织函数增加实例函数,则需要用到组织函数的prototype :

Person.prototype.breath = function(){ /*...*/ };
var person = new Person;
person.breath();

一种经常使用的形式是给类的 prototype 起一个别号fn,写起来也更简朴:

Person.fn = Person.prototype;
Person.fn.run = function(){ /*...*/ };

这类形式在jQuery 的插件开辟中是很罕见的,将函数增加至jQuery.fn 中也就相当于增加至jQuery 的原型中。

给完成了类机制的类库增加要领

给类增加属性和给组织函数增加属性是一样的。

直接给类设置属性和设置其静态成员是等价的:

var Person = new Class;

// 直接给类增加静态要领
Person.find = function(id){ /* ... */ };

// 如许我们能够直接挪用它们
var person = Person.find(1);

给类的原型设置的属性在类的实例中也是可用的:

var Person = new Class;

// 在原型中定义函数
Person.prototype.save = function(){ /* ... */ };

// 如许就能够在实例中挪用它们
var person = new Person;
person.save();

如许很难一眼就分辨出类的静态属性和实例的属性。因而我们采纳别的一种差别的要领来给类增加属性,这里用到了两个函数extend()include()

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

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

    // 定义 prototype 的别号
    klass.fn = klass.prototype;

    // 定义类的别号
    klass.fn.parent = klass;

    // 给类增加属性
    klass.extend = function (obj) {
        var extended = obj.extended;
        for (var i in obj) {
            klass[i] = obj[i];
        }
        if (extended) 
            extended(klass)
    };

    // 给实例增加属性
    klass.include = function (obj) {
        var included = obj.included;
        for (var i in obj) {
            klass.fn[i] = obj[i];
        }
        if (included) 
            included(klass)
    };
    return klass;
};

这段代码运用extend() 函数来天生一个类,这个函数的参数是一个对象。经由过程迭代将对象的属性直接复制到类上:

var Person = new Class;
Person.extend({
    find: function(id) { /* ... */ },
    exists: functions(id) { /* ... */ }
});
var person = Person.find(1);

include() 函数的事情道理也一样,只不过不是将属性复制至类中,而是复制至类的原型中。换句话说,这里的属性是类实例的属性,而不是类的静态属性。

var Person = new Class;
Person.include({
    save: function(id) { /* ... */ },
    destroy: functions(id) { /* ... */ }
});
var person = new Person;
person.save();

同样地,这里的完成支撑extended 和included 回调。将属性传入对象后就会触发这两
个回调:

Person.extend({
    extended: function(klass) {
        console.log(klass, " was extended!");
    }
});

这类写法已能够支撑模块了。模块是可重用的代码段,用这类要领能够完成种种继续,用来在类之间
同享通用的属性。

var ORMModule = {
    save: function(){
        // 同享的函数
    }
};

var Person = new Class;
var Asset = new Class;
Person.include(ORMModule);
Asset.include(ORMModule);
    原文作者:JingDing
    原文地址: https://segmentfault.com/a/1190000002498264
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞