1.对象适合于收集和管理数据,容易形成树型结构。 Javascript包括一个原型链特性,允许对象继承另一对象的属性。正确的使用它能减少对象的初始化时间和内存消耗。 2.函数它们是javascript的基础模块单元,用于代码复用、信息隐藏和组合调用。函数用于指定对象的行为。一般来说,编程就是将一组需求分解成一组函数和数据结构的技能。 3.模块我们可以使用函数和闭包来构造模块。模块是一个提供接口却隐藏实现状态和实现的函数或对象。
1. カスタム型 -- コンストラクター モード (疑似クラス モード)
クラスベースのシステムでは、オブジェクトは、それがどのようなものであるかを記述するクラスを使用して定義されます。建築が階級制であれば、建築家はまず家の設計図を描き、その設計図に従って家を建てることになります。
カスタム型パターンを使用して継承を実装する場合、必要なのは、パラメーターをコンストラクターに渡してから、インスタンス オブジェクトにパラメーターをマウントすることだけです。インスタンス オブジェクトによって呼び出されるメソッド内でパラメータにアクセスできるため、インスタンス オブジェクトの他のメソッドはパラメータを渡す必要はありません。インスタンスの this オブジェクトにマウントされる変数はインスタンス変数と呼ばれます。
構成 -- 継承
function Person (name, age, job) { // 实例变量 this.name = name; this.age = age; this.job = job; } Person.prototype.sayName = function () { alert(this.name); } var person1 = new Person('Nicholas', 29, 'Software Engineer'); var person2 = new Person('Greg', 27, 'Doctor'); function SuperType (name) { this.name = name; this.colors = ['red','blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType (name, age) { // 继承属性 SuperType.call(this,name); this.age = age; } // 继承方法 SubType.prototype = new SuperType(); SubType.prototype.sayAge = function () { console.log(this.age) } var instance1 = new SubType('Nicholas', 29); instance1.colors.push('black') console.log(instance1.colors); instance1.sayName(); instance1.sayAge(); var instance2 = new SubType('Greg', 27) console.log(instance2.colors); instance2.sayName(); instance2.sayAge();
継承されたプロパティと継承されたメソッドに関して、サブクラス コンストラクターのプロトタイプを作成するために new を通じてスーパークラス コンストラクターを呼び出したときに、問題が発生しました。スーパークラス コンストラクターのインスタンスであるため、スーパークラス コンストラクター内のインスタンス オブジェクトにも属性が追加されますが、値は未定義です。つまり、サブクラス トランスフォーマーを変更するために new を通じてスーパークラス コンストラクター関数が呼び出されます。サブクラス コンストラクターのプロトタイプが使用される場合、サブクラス コンストラクターのプロトタイプには冗長な属性が存在します。これにより無駄が生じます。実際に必要なのは、サブクラス コンストラクターのプロトタイプがスーパークラス コンストラクターのプロトタイプのメソッドを継承できることです。それで必要なものは、
1. サブクラスのコンストラクター プロトタイプ オブジェクトを作成します。
2. このサブクラス コンストラクターのプロトタイプは、スーパークラス コンストラクターのプロトタイプを継承します。
3. 1.でサブクラスコンストラクターのプロトタイプオブジェクトを書き換えた、つまりプロトタイプオブジェクトを再作成したため、新しく作成したプロトタイプオブジェクトにコンストラクター属性を追加し、サブクラスコンストラクターの関数に代入する必要があります。
上記のコードを次のように書き換えます。
コンストラクター属性について: この属性はコンストラクター関数のプロトタイプでのみ使用可能であり、書き換えられたプロトタイプ オブジェクトにはデフォルトではコンストラクター属性がありません。
寄生結合 - 継承
function inheritPrototype (subType,superType) { var prototype = Object.creat(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; }; function SuperType (name) { this.name = name; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType(name, age) { //继承属性 SuperType.call(this,name); this.age = age; } //继承方法 inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function () { console.log(this.age); } var instance = new SubType();
これらのいわゆるプロトタイプ操作の詳細を隠すことで、奇妙に見えなくなりました。しかし、本当に何かを発見しましたか?
プライベート環境はなく、すべてのプロパティはパブリックです。親クラスのメソッドにアクセスできません。デバッグが難しい
2. プロトタイプ
純粋なプロトタイプ パターンでは、クラスを放棄し、代わりにオブジェクトに焦点を当てます。プロトタイプベースの継承は、概念的にはクラスベースの継承よりも単純です。新しいオブジェクトは古いオブジェクトのプロパティを継承できます。まず便利なオブジェクトを構築し、その後、そのオブジェクトに似たオブジェクトをさらに構築できます。これにより、アプリケーションを一連のネストされた抽象クラスに分割する分類プロセスを完全に回避できます
プロトタイプベースのシステムでは、必要なそのタイプのすべてのオブジェクトに似たオブジェクトを作成し、そのようなオブジェクトがさらに必要であることを JavaScript エンジンに伝えます。もし建築がプロトタイプに基づいているなら、建築家はまず家を建て、それからすべての家をこのように建てるでしょう。
メソッド Object.creat() は、new 演算子の代替手段であり、JavaScript オブジェクトの作成に使用すると、よりプロトタイプベースの感覚を追加できます。
function myMammal = { name : 'Herb the Mammal', get_name : function () { return this.name; }, says : function () { return this.saying || ''; } } var myCat = Object.create(myMammal); myCat.name = 'Henrietta'; myCat.saying = 'meow'; myCat.purr = function (n) { var i, s = ''; for (i = 0;i < n; i += 1) { if(s) { s += '-' } s += 'r'; } return s; } myCat.get_name = function () { return this.says + ' ' + this.name + this.says; }
这是一种"差异化继承"。通过定制一个新的对象,我们指明它与所基于的基本对象的区别。
有时候,它对某些数据结构继承于其他数据结构的情形非常有用。
3.函数化--工厂模式
在伪类模式里,构造器函数Cat不得不重复构造器Mammal已经完成的工作。在函数化模式中那不再需要了,因为构造器Cat将会调用构造器Mammal,让Mammal去做对象创建中的大部分工作,所有Cat只关注自身的差异即可。
函数化模式有很大的灵活性。它相比伪类模式不仅带来的工作更少,还让我们得到更好的封装和信息隐藏,以及访问父类方法的能力。
如果我们用函数化得样式去创建对象,并且该对象的所有方法都不用this或that,那么该对象就是持久性的。一个持久性的对象就是一个简单功能函数的集合。
私有变量:任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。
闭包
闭包是阻止垃圾回收器将变量从内存中移除的方法,使的在创建变量的执行环境的外面能够访问到该变量。
请记住:闭包由函数创建。每次调用函数会创建一个唯一的执行环境对象。函数执行完后,执行对象就会被丢弃,除非调用者引用了它。当然,如果函数返回的是数字,就不能引用函数的执行环境对象。但是如果函数返回的是一个更复杂的结构,像是函数、对象或者数组,将返回值保存到一个变量上,就创建了一个对执行环境的引用。
Function.prototype.method = function (name,func) { this.prototype[name] = func; return this; } // 工厂mammal函数 var mammal = function (spec) { var that = {}; that.get_name = function () { return spec.name; } that.says = function (spec) { 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'; } } that.get_name = function () { return that.says() + ' ' + spec.name + ' ' + that.says(); } return that; } // 创建myCat对象 var myCat = cat({name: 'Henrietta'}); Object.method('superior',function (name) { var that = this, method = that[name]; return function () { return method.apply(that, arguments) } }) // 工厂coolcat函数(基于cat函数) var coolcat = function (spec) { var that = cat(spec), super_get_name = that.superior('get_name'); that.get_name = function (n) { return 'like ' + super_get_name() + ' baby'; } return that; } var myCoolCat = coolcat({name : 'Bix'}); var name = myCoolCat.get_name();
函数化模块模式有很大的灵活性。它相比构造函数模式不仅带来的工作更少,还让我们得到更好的封装休息和隐藏,以及访问父类方法的能力。如果对象的所有状态都是私有的,那么该对象就成为一个"防伪(tamper-proof)"对象。该对象的属性是可以被替换或者删除,当该对象的完整性不会受到损坏。我们用函数式的样式创建一个对象,并且该对象的所有方法都不使用this或者that,那么该对象就是持久性对象。一个持久性对象,就是一个简单的函数功能的集合。
一个持久性的对象不会被入侵。访问一个持久性的对象时,除非有方法授权,否则攻击者不会访问对象的内部状态。
模块模式
前面的模式是用于 自定义类型创建私有变量和特权方法的。而道格拉斯所说的模块模式则是为 单例创建私有变量和特权方法。所谓单例指的就是只有一个实例的对象。(就是用对象字面量表示法创建的对象)
var singleton = function () { // 私有变量和函数 var privateVariable = 10; function privateFunction () { return false; } //特权/公有方法和属性 return { publicProvperty: true; publicMethod: function () { privateVariable++; return privateFunction(); } } }
从本质上讲,这个对象字面量定义的是单例的公共接口。这种模式在需要对单例进行某些初始化,同时又需要维护其私有变量时非常有用。简言之,如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法。
增强的模块模式
这种增强的模块模式适合那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的例子。
var singleton = function () { // 私有变量和函数 var privateVariable = 10; function privateFunction () { return false } // 创建对象 var object = new CustomType(); // 添加特权/公有属性和方法 object.publicProperty = true; object.publicMethod = function () { privateVariable++; return privateFunction(); } return object; }()