JavaScript设计模拟

原型模式和基于原型继承的JavaScript对象系统

使用克隆的原型模式
var Plane = function(){ this.blood = 100; this.attackLevel = 1;     this.defenseLevel = 1;
};
var plane = new Plane(); plane.blood = 500; plane.attackLevel = 10; plane.defenseLevel = 7;
var clonePlane = Object.create( plane );
console.log( clonePlane ); // 输出:Object {blood: 500, attackLevel: 10, defenseLevel: 7}
在不支持 Object.create 方法的浏览器中,则可以使用以下代码:
Object.create = Object.create || function( obj ){ var F = function(){};
F.prototype = obj;
return new F(); }    

JavaScript中的原型继承

JavaScript 也同样遵守这些原型编程的基本规则。

 所有的数据都是对象。
 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它。  对象会记住它的原型。
 如果对象无法响应某个请求,它会把这个请求委托给它自己的原型。

下面我们来分别讨论 JavaScript 是如何在这些规则的基础上来构建它的对象系统的。

1. 所有的数据都是对象

JavaScript 在设计的时候,模仿 Java 引入了两套类型机制:基本类型和对象类型。基本类型 包括 undefined、number、boolean、string、function、object。从现在看来,这并不是一个好的 想法。

按照 JavaScript 设计者的本意,除了 undefined 之外,一切都应是对象。

事实上,JavaScript 中的根对象是 Object.prototype 对象。Object.prototype 对象是一个空的 对象。我们在 JavaScript 遇到的每个对象,实际上都是从 Object.prototype 对象克隆而来的, Object.prototype 对象就是它们的原型。比如下面的 obj1 对象和 obj2 对象:

var obj1 = new Object(); var obj2 = {};

可以利用 ECMAScript 5 提供的 Object.getPrototypeOf 来查看这两个对象的原型:

console.log( Object.getPrototypeOf( obj1 ) === Object.prototype ); // 输出:true

console.log( Object.getPrototypeOf( obj2 ) === Object.prototype ); // 输出:true

2. 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它

3. 对象会记住它的原型

JavaScript 给对象提供了一个名为__proto__的隐藏属性,某个对象的__proto__属性默认会指 向它的构造器的原型对象,

即{Constructor}.prototype。在一些浏览器中,__proto__被公开出来, 我们可以在 Chrome 或者 Firefox 上用这段代码来验证:

var a = new Object();
console.log ( a.__proto__=== Object.prototype ); // 输出:true

4. 如果对象无法响应某个请求,它会把这个请求委托给它的构造器的原型

这条规则即是原型继承的精髓所在。从对 Io 语言的学习中,我们已经了解到,当一个对象 无法响应某个请求的时候,它会顺着原型链把请求传递下去,直到遇到一个可以处理该请求的对 象为止。

this的指向

除去不常用的 with 和 eval 的情况,具体到实际应用中,this 的指向大致可以分为以下 4 种。

 作为对象的方法调用。
 作为普通函数调用。
 构造器调用。
 Function.prototype.call 或 Function.prototype.apply 调用。

1. 作为对象的方法调用 当函数作为对象的方法被调用时,this 指向该对象:

var obj = {

  a: 1,

  getA: function(){
    alert ( this === obj ); // 输出:true alert ( this.a ); // 输出: 1

  }

};

obj.getA();

2. 作为普通函数调用 当函数不作为对象的属性被调用时,也就是我们常说的普通函数方式,此时的 this 总是向全局对象。在浏览器的 JavaScript 里,这个全局对象是 window 对象。

window.name = 'globalName';
var getName = function(){ 
    return this.name;
};
console.log( getName() );// 输出:globalName
或者:
window.name = 'globalName';
var myObject = { 
    name: 'sven',
    getName: function(){ 
        return this.name;
    } 
};
 var getName = myObject.getName;
 console.log( getName() ); // globalName 

call和apply的用途

1. 改变 this 指向

2. Function.prototype.bind

Function.prototype.bind = function( context ){ 
    var self = this; // 保存原函数
    return function(){ 
        return self.apply( context, arguments );// 返回一个新的函数
      // 执行新的函数的时候,会把之前传入的 context 
    // 当作新函数体内的 this
} };
var obj = {
    name: 'sven'
};
var func = function(){ 
    alert ( this.name );
}.bind( obj); 
func();// 输出:sven   

3. 借用其他对象的方法-这个对象至少还要满足:

 对象本身要可以存取属性;

 对象的 length 属性可读写。

var a = {};
Array.prototype.push.call( a, 'first' );
alert ( a.length ); // 输出:
alert ( a[ 0 ] ); // first

u

原文地址:https://www.cnblogs.com/chenzxl/p/12023299.html