伪类
当一个函数对象被创建时,Function构造器产生的函数对象会运行类似这样的代码:
this.prototype = {constructor: this};
当采用构造器调用模式,即使用new前缀去调用一个函数时,这将修改函数执行的方式。如果new运算符是一个方法而不是一个运算符,它可能会像这样执行:
Function.method('new', function(){
//beget函数在《对象》这章出现,创建一个新对象,继承自构造器函数的对象原型
var that = Object.beget(this.prototype);//this指向调用new函数的具体function。
var other = this.apply(that, arguments);
return (typeof other === 'object' && other)||that;
});
构造器函数的缺陷:
- 没有私有环境 所有的属性是公开的, 无法访问super(父亲)的方法。
- 如果忘记使用new前缀 , 那么this将不会被绑定到一个新对象上,同时,this绑定在全局变量上,不但没有扩充新对象,反而将破坏全局变量,并且没有提警告。
对象说明符
在编写构造器时使其接受一个简单的对象说明符可能会更加友好。那个对象包含了将要构建的对象规格说明。与其这样写
var myObject = maker(f,l,,m,s,c);
不如这么写:
var myobject = maker{{
first: f,
last: l,
state: s,
city: c
}}
原型
var myMammal = {
name: 'Herb the Mammal',
get_name: function(){
return this.name;
},
says: function(){
return this.saying||'';
}
}
差异化继承: 通过定制一个新对象,指明它与所基于的基本对象的区别。
用处:对某种数据结构从其他数据结构继承的情形。
var myCat = Object.beget(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'mm';
myCat.purr = function(n){
return n;
}
myCat.get_name = function(){
return this.says+' '+this.name;
}
函数化
构造一个不需要new前缀产生对象的函数,包括以下几个步骤:
- 创建一个新对象。
- 选择性的定义私有实例变量和方法。这些就是函数通过var语句定义的普通变量。
- 给新对象扩充方法。拥有特权去访问方法
- 返回新对象 。
var mammal = function(spec){
var that = {};
that.get_name = function(){
return spec.name;
};
that.says = function(){
return spec.saying||'';
}
return that;
}
cat继承mammal;
var cat = function(spec){
spec.saying = spec.saying||'meow';
var that = mammal(spec);
that.purr = function(n){
var i, s = '';
for(i = 0;i<n;i+=1){
if(s){
s+='-';
}
s+='r';
}
return s;
};
that.get_name = function(){
return that.says()+' ' + spec.name + ' ' +that.says();
}
return that;
}
var myCat = cat({name: 'Henrietta'});
如果对象的所有状态都是私有的,那么该对象就成为一个‘防伪(tamper-proof)’对象。该对象的属性可以被替换或删除,但该对象的完整性不会受到损害。如果我们用函数化的样式创建一个对象,并且该对象的所有方法都不使用this或that,那么该对象就是持久性的。一个持久性的对象就是一个简单功能函数的集合。
部件
var eventuality = function(that) {
var registry = {};
that.fire = function(event){
var array, func, handler,i,type;
type = typeof event === 'string'?event:event.type;
//如果这个事件存在一组事件处理程序中, 那么就遍历它们并按顺序依次执行。
if(registry.hasOwnProperty(type)){
array = registry[type];
for(i = 0;i<array.length;i+=1){
handler = array[i];
func = handler.method;
if(typeof func === 'string'){
func = this[func];
}
//调用一个处理程序,如果该条目包含参数,那么传递它们过去。否则,传递该事件对象,
func.apply(this, handler.parameters||[event]);
}
}
return this;
};
//注册和绑定事件
that.on = function(type, method, parameters){
var handler = {
method: method,
parameters: parameters
};
if(registry.hasOwnProperty(type)){
registry[type].push(handler);
}else{
registry[type] = [handler];
}
return this;
};
return that;
}