Javascript Web Application笔记之MVC和类 - 类的创建 类库的封装与JSON方式添加函数

1、使用new关键字:

new 运算符改变了函数的执行上下文,同时改变了return 语句的行为。实际上,使用new和构造函数很类似于传统的实现了类的语言:

// 使用new创建对象
var Person = function(name) {
this.name = name;
};
// 实例化一个Person
var alice = new Person(‘alice’);
// 检查这个实例
alert( alice instanceof Person );

注意:不要用省略new前缀的方式来调用构造函数:

var jason = Person(“arthinking”);
alert(jason); // undefined

解释:这个函数只会返回undefined,并且执行上下文是window(全局)对象,你无意间创建了一个全局变量name。当使用new 关键字来调用构造函数时,执行上下文从全局对象(window)变成一个空的上下文,这个上下文代表了新生成的实例。

2、构造函数中的返回值:

默认情况下,如果你的构造函数中没有返回任何内容,就会返回this。也可以自定义返回值:

var Class = function(){
var klass = function(){
// apply 修改函数上下文,详见:http://www.itzhai.com/javascript-notes-javascript-function.html 1.4 函数上下文
// 这里即执行了init初始化函数,把实际执行这段代码的类的上下文传入到这里。
this.init.apply(this, arguments);
};
klass.prototype.init = function(){};
// 返回自定义的变量
return klass;
};

alert(Class); // 输出匿名函数Class

var Person = new Class; // Class的this范围中没有init函数,但可以通过prototype添加该方法到Person,在new Person就会执行添加的init方法了

alert(Person); // 输出匿名函数klass 可见new关键字就是创建了类中所有的变量
Person.prototype.init = function(){
alert(“基于Person的实例做初始化”);
};

// 用法
var person = new Person; //调用init函数进行初始化
alert(person);

3、给类添加函数,静态函数和实例函数:

// 直接调用静态函数
Person.find = function(id){ // };
Person.find(“abc”);
// 通过类调用实例函数
Person.prototype.breath = function(){ // };
var person = new Person();
person.breath();

一种常用的模式是给类的prototype起个别名,方便使用:

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

可以看到,静态函数相当于一个变量,可以通过类直接调用。实例函数,既是通过原型链添加的,都需要先用new关键字创建出对象,之后通过对象调用的。

4、给类库添加方法:

上面已经展示了如何给一个类添加静态方法和实例方法,以及它们的使用。下面分别添加两个方法:extend用于添加类的属性,include用于添加实例的属性。

var Class = function(){
var klass = function(){
// apply 修改函数上下文,详见:http://www.itzhai.com/javascript-notes-javascript-function.html 1.4 函数上下文
// 这里即执行了init初始化函数,把实际执行这段代码的类的上下文传入到这里。
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;

};

4.1、extend()的使用:

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

4.2、include()的使用:

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

这种写法之美在于它已经可以支持模块了。模块是可重用的代码段,用这种方法可以实现各种继承,用来在类之间共享通用的属性。

arthinking wechat
欢迎关注itzhai公众号