コードは次のとおりです:
/****************** Object-oriented ******************/
/********** 1: Object creation, prototype chain **********/
/* It is important to discuss constructor (class method) to create objects and understand these contents in depth
*/
function MyFunc() { }; //Define an empty function
var anObj = new MyFunc(); //Use the new operator and use the MyFun function to create an object
//Equivalent to:
function MyFunc() { };
var anObj = {}; //Create an object
anObj.__proto__ = MyFunc.prototype;
MyFunc.call(anObj) ; //Call the MyFunc function using the anObj object as this pointer
/*
The process of creating an object in the form of var anObject = new aFunction() can actually be divided into three steps:
Step 1: Create a New object (anObject);
Step 2: Set the object’s built-in prototype object (__proto__) to the prototype object referenced by the constructor prototype;
Step 3: Call the constructor with the object as this parameter , complete initialization work such as member setting.
After the object is created, any access and operation on the object are only related to the object itself and the string of objects on the prototype chain.
It has nothing to do with the constructor.
In other words, the constructor only plays the role of introducing the prototype object and initializing the object when creating an object.
Prototype chain: (Reference: http://hi.baidu.com/fegro/blog/item/41ec7ca70cdb98e59152eed0.html)
Each object (the object here should only refer to the object enclosed in curly brackets, not Including function, array. To be verified? )
will initialize an attribute inside it, which is __proto__. When we access the attribute of an object,
If this attribute does not exist inside the object, then it will Find this attribute in __proto__,
This __proto__ will have its own __proto__, so we keep looking for it, which is what we usually call the concept of prototype chain.
*/
/* After understanding the principle of object creation, you can try to analyze the results of the two examples below*/
var yx01 = new function() {return "Circle Center"};
alert (yx01); // [object Object]
var yx02 = new function() {return new String("center of circle")};
alert(yx02); // "center of circle"
/* Explanation :
"Circle Center" is the basic string type, and new String("Circle Center") creates a string object.
As long as the constructor after the new expression returns a reference object (array, object, function, etc.), it will overwrite the object created by new.
If it returns a primitive type (when there is no return, it actually returns the primitive type undefined ),
then return the object created by new.
Reference: http://www.planabc.net/2008/02/20/javascript_new_function/
*/
/********** 2: Data type detection **********/
/* What you may think of when judging the data type Methods:
constructor, typeof, instanceof, Object.prototype.toString.call()
*/
/***** 1. Through constructor attribute *****/
var myvar= new Array("a"," b","c","d");
function A(){}
myvar.constructor = A;
var c = myvar.constructor;
alert(c); // function A(){}
//It can be seen that the method of obtaining the type through the constructor attribute is easily modified and should not be used to determine the type.
/***** 2. Through typeof *****/
/*
typeof is an operator, not a function.
The practical application of typeof is to detect whether an object has been defined or assigned a value.
For example, if(typeof a!="undefined"){}, do not use if(a) because if a does not exist (undeclared), an error will occur.
When typeof detects the object type, it can generally only return the following results:
number, boolean, string, function, object, undefined.
Using typeof for Array, Null, custom objects, etc. will always return object.
This is the limitation of typeof.
*/
var num = new Number(1);
var arr = [1,2,3];
alert(typeof num); //object instead of number
alert (typeof arr); //object instead of Array
alert(typeof null); // object
/***** 3. Through instanceof *****/
/* Use instanceof operator to determine whether the object is an object Instance of class.
If obj instanceof Class returns true, then the prototype of Class is the same object as a prototype on the obj prototype chain,
that is, obj is either created by Class or a subclass of Class.
*/
function t(){};
t.prototype = Array.prototype;
//t.prototype = [];
var x = new t();
alert(x instanceof t);//pop true
alert(x instanceof Array);//pop true
alert(x instanceof Object);//pop true
/*
by It can be seen that judging the data type through instanceof is not reliable either.
Because the prototype chain of an object (here x) can be very long, the type of each prototype can be different.
In addition, it is also easy to make errors within an iframe:
That is, there is a page that defines an array a, and the page has an IFrame nested in it. If top.a instanceof Array is passed in the Iframe, it will return false.
This description indicates that the objects in the parent page and the embedded iframe are different and cannot be mixed together.
top.ainstanceoftop.Array に変更すると true が返されます
*/
/***** 4. Object.prototype.toString.call() を通じて *****/
/*
Object.prototype.toString.call() 関数 Itは:
1. オブジェクトのクラス名 (オブジェクト型) を取得します。
2. 次に[オブジェクト、取得したクラス名]を結合して返します。
配列、日付、関数、その他の型のオブジェクトを決定するために使用できます。
*/
var num = new Number(1);
var arr = [1,2,3]; 🎜>alert(Object.prototype.toString.call(num)); // [オブジェクト番号]
alert(Object.prototype.toString.call(arr)) // [オブジェクト配列]
//拡張例: (apply は call と同等)
window.utils = {
toString: Object.prototype.toString,
isObject: function (obj) {
return this.toString.apply(obj) ) = == '[オブジェクト オブジェクト]';
},
isFunction: function (obj) {
return this.toString.apply(obj) === '[オブジェクト関数]'; >} ,
isArray: function (obj) {
return this.toString.apply(obj) === '[オブジェクト配列]';
}
}
function A() { }
window.utils.isFunction(A); //true
window.utils.isObject(new A()); //true
window.utils.isArray([]); true
/*
jQuery などのフレームワークではこのメソッドを使用してオブジェクトの種類を判定するため、権威のある判定方法として利用できます。
ただし、Object.prototype.toString メソッドをオーバーライドすると、それを使用してデータ型を決定するときにエラーが発生する可能性があります。
そのため、通常は Object.prototype.toString メソッドをオーバーライドしないでください。
*/
/********** 3: 相続 **********/
/*
クロージャと同様に、JS の継承は、JS を詳しく学びたいほぼすべての友人が議論しなければならない問題です。すべての関連情報が入手可能です。
JS 継承コードには多くのバージョンがありますが、原則は同じで、コアはプロトタイプ オブジェクトを使用します。
他のオブジェクト指向言語のスタイルに似せるために、そのほとんどは「クラス」スタイルのシミュレーションを使用します。
継承の詳細な原則については詳しく説明しません。インターネット上には多くの情報があります。
これは例です: Jquery 作者 John Resig によって書かれた継承。
(詳細なコメントはブログからのものです。誰が作成したかわからないため、ここに非公開で再投稿します)
*/
(function () {
// 初期化変数が使用されます)現在のクラスの作成フェーズにあるかどうかをマークします。
// - クラスの作成フェーズではプロトタイプ メソッド init を呼び出すことはできません
// - この問題については、第 3 回で詳しく説明しています。このシリーズの記事
// fnTest は正規表現です。取り得る値は (/b_superb/ または /.*/) です。
// - /xyz/.test(function() のテスト) { xyz; }) は、ブラウザーがテスト パラメーターが関数である場合をサポートしていますか?
// - ただし、IE7.0、Chrome2.0、および FF3.5 をテストしたところ、このテストはすべて true を返しました。
// - したがって、fnTest に値を割り当てることはほとんどの場合正しいです: fnTest = /b_superb/;
varInitializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /b_superb/ : /.*/ ;
// 基本クラスのコンストラクター
// これは window なので、このコード全体が外部の世界へのウィンドウを開きます - window.Class
this。 Class = function () { } ;
// 継承されたメソッド定義
Class.extend = function (prop) {
// ここは非常にわかりにくいので、このシリーズの 2 番目の記事で述べたことを思い出してください。
// - これが具体的に何を指すのかは、定義時には決定できませんが、この関数の呼び出し方法によって異なります。
// - extend はコンストラクターとしてではなくメソッドとして呼び出す必要があることはすでにわかっています
// - したがって、ここでは this はオブジェクトではなく関数 (つまり、クラス) を指しています。その場合、this.prototype は親クラスのプロトタイプ オブジェクトです。
// - 注: _super は親クラスのプロトタイプ オブジェクトを指します。親クラスの場合、次のコードでこの変数に何度も遭遇します
var _super = this.prototype;
// サブクラスのプロトタイプを親クラスのインスタンス オブジェクトにポイントすることで継承が完了します
// - 注: this は基本クラスのコンストラクター (つまり、クラス)
initializing = true;
varprototype = new this();
initializing = false;コードは作者によって最適化されているため、非常に単刀直入に読めます。後で詳しく説明します。
for (var name in prop) {
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "関数" && fnTest.test(prop[name]) ?
(function (name, fn) {
return function () {
var tmp = this._super; // ここは必要に応じて、91 行目のコメント コードで説明できます。
this._super = _super[名前];
var ret = fn.apply(this, argument);
return
; })(name, prop[name]):
prop[name];
}
// この場所から、Resig は変装が非常に上手であることがわかります
// - を使用します同じ名前のローカル変数を使用してグローバル変数をオーバーライドすると、非常に混乱します
// - 発音しにくい場合は、関数 Class() の代わりに関数 F() などの別の名前を使用できます
// - 注: ここでの Class は、最外層で定義された基本クラスのコンストラクターではありません
// ここでの Class は、上記の window.Class 関数とは異なります。ここでは、window.Class
function 内の関数ローカル変数を示します。 Class() {
// クラスをインスタンス化するときに、プロトタイプ メソッド init
if (!initializing && this.init)
this.init.apply(this, argument); を呼び出します。 🎜>// サブクラスのプロトタイプは、親クラスのインスタンスを指します (継承を完了するためのキー)
Class.prototype =prototype; // クラスは、初期ウィンドウではなく、上のクラスを参照します。Class
// コンストラクターのポインティングエラーを修正します
// Class.prototype.constructor = Class; を使用することで修正できますか? ? ?
Class.constructor = Class;
// サブクラスは、現在実行中の関数を指す extend メソッドを自動的に取得します。
Class.extend = argument.callee;
> };
})();