公然纪录进修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
改成_class
或klass
。
给类增加函数
在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);