资讯专栏INFORMATION COLUMN

JavaScript MVC 学习笔记(二)类的使用(上)

caozhijian / 2146人阅读

摘要:任何函数都可以用做构造函数,构造函数必须使用运算符作为前缀来创建新的实例。当使用关键字来调用构造函数时,执行上下文从全局对象变成一个空的上下文,这个上下文代表了新生成的实例。默认情况下,如果构造函数中没有返回任何内容,就会返回当前的上下文。

公开记录学习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);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85500.html

相关文章

  • JavaScript MVC 学习笔记(三)类的使用(中)

    摘要:实际上,可以将其理解为某种形式的继承。如果上下文是,则使用全局对象代替。例如的第个参数是上下文,后续是实际传入的参数序列中允许更换上下文是为了共享状态,尤其是在事件回调中。 公开记录学习JS MVC,不知道能坚持多久= =。以《基于MVC的JavaScript web富应用开发》为主要学习资料。接上一篇类的学习,发现实在是看晕了,有些例子是能看懂在干嘛,但是不知道为什么这样做,有的甚至...

    DandJ 评论0 收藏0
  • JavaScript MVC 学习笔记(四)类的使用(下)

    摘要:基于函数进行调用的,用来确保函数是在指定的值所在的上下文中调用的。添加私有函数目前上面为类库添加的属性都是公开的,可以被随时修改。以基于的富应用开发为主要学习资料。 控制类库的作用域 在类和实例中都添加proxy函数,可以在事件处理程序之外处理函数的时候保持类的作用域。下面是不用proxy的办法: var Class = function(parent){ var klas...

    Rango 评论0 收藏0
  • React学习笔记—Why React?

    摘要:官方说法注本人英语二十六级是和用来创建用户界面的库。很多人将认为是中的。怎么说呢现在的自己就是个跟风狗啊,什么流行先学习了再说,再看看能不能应用在具体项目上。暂时先停下的学习,坐等。不过学习的脚步还是跟不上潮流的发展速度啊。 Why React? 官方说法 注:本人英语二十六级 React是Facebook和Instagram用来创建用户界面的JavaScript库。很多...

    余学文 评论0 收藏0
  • JavaScript MVC 学习笔记(一)初识JS MVC

    摘要:以基于的富应用开发为主要学习资料。下面用实现一个例子使用匿名函数来封装一个作用域在页面加载时绑定事件监听上面的代码创建了控制器,这个控制器是放在变量下的命名空间。然后用了一个匿名函数封装了一个作用域,以避免对全局作用域造成污染。 公开记录学习JS MVC,不知道能坚持多久= =。以《基于MVC的JavaScript web富应用开发》为主要学习资料。 什么是MVC MVC 是一种设...

    xorpay 评论0 收藏0
  • JavaScript MVC 学习笔记(六)模型之ORM

    摘要:模型应当从视图和控制器中解耦出来。与数据操作和行为相关的逻辑都应当放入模型中,通过命名空间进行管理。在应用中,对象关系映射也是一种非常有用的技术,它可以用来做数据管理及用做模型。以基于的富应用开发为主要学习资料。 MVC 和命名空间 要确保应用中的视图、状态和数据彼此清晰分离,才能让架构更加整洁有序且更加健壮。模型应当从视图和控制器中解耦出来。与数据操作和行为相关的逻辑都应当放入模型...

    mrcode 评论0 收藏0

发表评论

0条评论

caozhijian

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<