JAvascriptノート:javascript内のオブジェクトの作成を深く分析する(上)

23959 ワード

jQueryソースを読むとき、私はいつもそれらの要素が私にコードを読めないことを考えています.その中で最も重要なのはどれですか.最も早くjQueryのアーキテクチャ設計だと思っていました.資料を調べてやっとjQueryアーキテクチャ設計の入り口を見つけたとき、javascriptの基礎文法の熟練した運用がソースコードを読む鍵であることに気づきました.そのため、今javascriptの基礎知識システムを振り返る必要があります.そして、jQueryソースの研究はjavascriptの基礎知識の深さと柔軟な運用です.jQueryを模写すると、javascriptの基礎知識の学習と挿入されると思います.そうすれば、きっと各難問にもっとよく答えられると思います.
最近javascriptを深く勉強した後、オブジェクト向けのプログラミングこそ効率的で柔軟なプログラミングであり、コードをより丈夫にする唯一のプログラミングでもあることを体得しました.もし私たちがそれらの玄乎な抽象出類などの思想を捨てて、私自身が対象に対する書くプログラムの角度から理解するのは:多重化とカプセル化です.多重化は具体的には、重複コードをできるだけ少なく書くことです.カプセル化は、結合度の高い論理をプログラムブロックに入れ、できるだけ内容が外部の影響を受けないようにすることです.最後の結論は,優秀なjavascriptコードはいずれもオブジェクト向けである.
今日はjavascriptオブジェクトを構築する方法について説明します.
ECMA-262オブジェクトの定義は、基本値、オブジェクト、または関数を含む無秩序属性の集合です.JAvascriptのオブジェクトは、実はjavaのmap、すなわちキー値ペアです.
Javascriptでオブジェクトを作成するには、3つの方法があります.方法1:Objectオブジェクトによる方法2:関数を構築する方法3:オブジェクトの初期化
  1.オブジェクトをObjectオブジェクトで構築します.コードは次のとおりです.
//    Object    

var obj = new Object();
obj.id = '001';
obj.name = 'My name is obj';
obj.teststring = 'Test obj';
obj.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}

obj.sayHello();//id:001@!@name:My name is obj@!@teststring:Test obj
obj['sayHello']();//id:001@!@name:My name is obj@!@teststring:Test obj
var str = 'sayHello';
obj[str]();//id:001@!@name:My name is obj@!@teststring:Test obj

(注意:ここでは、点演算子と角カッコ演算子の2つのオブジェクト属性にアクセスする方法を使用していますが、両者は等価ですが、角カッコ演算はより強力なようです.角カッコの中に変数を置くことができます)
これは最もよく使われる、最も直感的なオブジェクトの作成方法ですが、その欠点は明らかです.コードの多重度が低いことです.オブジェクトを考えてオブジェクトを作成すると、多くの重複コードが発生します.そのため、javascriptプログラマーは工場モードをjavascripプログラミングに導入しました.次のコードを見てください.
//          

function createObj(id,name,teststring)
{
var o = new Object();
o.id = id;
o.name = name;
o.teststring = teststring;
o.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
return o;
}
var obj = createObj('002','My Name is obj2','Test Obj2');
obj.sayHello();//id:002@!@name:My Name is obj2@!@teststring:Test Obj2
obj['sayHello']();//id:002@!@name:My Name is obj2@!@teststring:Test Obj2
var str = 'sayHello';
obj[str]();//id:002@!@name:My Name is obj2@!@teststring:Test Obj2

ファクトリモードは似たようなオブジェクトを作成する問題を解決し、それを捨ててオブジェクトを構築するオブジェクト識別問題を解決すると、ファクトリモードは完璧です.javascriptアプリケーションが複雑ではない場合は、ファクトリモードを使用してオブジェクトを構築することをお勧めします.この書き方は読みやすいです.(工場モードまで書いて、jQueryの中に注釈があまり正確ではないようですが、これは後で修正します).
2.構造関数による
私の前の博文《javascriptノート:javascript前世続編(javascript起源からその継承を語る)》の中で私はjavascriptの起源からjavascriptのオブジェクト向けのいくつかの設計思想について話して、その中にjavascriptの構造関数に関する設計があります.ほとんどのコンストラクション関数を使用してオブジェクトを構築するにはnew演算子が使用されます.javascriptのコンストラクション関数は特別です.javascriptにはクラスの概念はありません.newの後ろにはコンストラクション関数が付いています.次のコードを見てください.
//           

function Obj(id1,name1,teststring1)
{
this.id = id1;
this.name = name1;
this.teststring = teststring1;
this.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
}

var obj = new Obj('003','My Name is obj3','Test Obj3');
obj.sayHello();//id:003@!@name:My Name is obj3@!@teststring:Test Obj3
obj['sayHello']();//id:003@!@name:My Name is obj3@!@teststring:Test Obj3
var str = 'sayHello';
obj[str]();//id:003@!@name:My Name is obj3@!@teststring:Test Obj3

構造関数式と工場モードはコードの角度から言えばとても似ていて、私はjavascriptの初期を勉強して、単独で1つの方式を見て、思考はいつも慣性的に両者を混同して話して、もし2つが一緒に置くならばやはり違いがあると感じて、主にjavascriptの中でfunctionが与えられた機能が多すぎて、1つの大型プログラムの中で2つが交互に使うならば、頭がくらくらしないのはおかしいです.実は両者の構造オブジェクトの違いによってfunctionの使用を構造関数式と関数式に分けることができます.次に私は重点的に2つの方式を分析して、ここの底は全面的ではないかもしれませんが、もしどの達人が見たら補充して指摘することができます.
まず、メソッドの各プロパティのthisポインタを外しますが、sayHelloで参照されているthisポインタは削除されません.コードは次のとおりです.
//         1
function Obj(id1,name1,teststring1)
{
id = id1;
name = name1;
teststring = teststring1;
sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
}
var obj = new Obj('004','My Name is obj4','Test Obj4');
sayHello();//id:undefined@!@name:@!@teststring:undefined
window.sayHello();//id:undefined@!@name:@!@teststring:undefined
obj.sayHello();//obj.sayHello is not a function [ ] obj.sayHello();

(修正:sayHello();とwindow.sayHello()結果はid:004@!@name:My Name is obj4@!@teststring:Test Obj 4、申し訳ありませんが、以下の分析にもいくつかの問題があります.本文の完全性を保証するために、ここでは修正だけをします.次の文章の冒頭で間違いの原因を重点的に分析します.
これは永遠にobjを指して、sayHelloの方法の中のthis.idなどの属性の値はundefinedで、Objのfunctionオブジェクトにid、name、teststring属性がないことを示し、sayHelloメソッドさえObjに定義されていないが、直接sayHello()である.sayHelloの方法を見つけることができて、最後にwindowを使います.sayHello();sayHelloがwindowに定義されていることを知った.もし私がObjの中のすべてのthisを削除したら、コードは以下の通りです.
//         2

function Obj(id1,name1,teststring1)
{
id = id1;
name = name1;
teststring = teststring1;
sayHello = function()
{
console.log('id:' + id + '@!@name:' + name + '@!@teststring:' + teststring);
}
}
var obj = new Obj('005','My Name is obj5','Test Obj5');
sayHello();//id:005@!@name:My Name is obj5@!@teststring:Test Obj5
window.sayHello();//id:005@!@name:My Name is obj5@!@teststring:Test Obj5
console.log(id);//005
console.log(name);//My Name is obj5
console.log(teststring);//Test Obj5
console.log(window.id);//005
console.log(window.name);//My Name is obj5
console.log(window.teststring);//Test Obj5

上記の内容から、私は次の結論を得ました.
一.JAvascriptはオブジェクト向けのプログラミングが可能で、プロセス向けの言語とすることはできません.
二.JAvascriptではオブジェクトの作成が特別で、特に従来のオブジェクト向け言語と比較して簡略化され、構造関数を直接使用してオブジェクトを作成することに簡略化されています.
三.functionはjavascriptの中で関数式として使用することができて、また構造関数の標識として(あなたも直接クラスとして見ることができます)、構造関数式と関数式を区別する違いはnewです;
四.コンストラクション関数式を使用してオブジェクトを作成する場合は、ここでは他のオブジェクト向け言語と同様にカプセル化されています.言い換えれば、定義された属性またはメソッドがオブジェクトに属し、そのオブジェクトに属させる方法はthisポインタを使用します.いいえ、属性とメソッドはwindowオブジェクトに属します.
new演算子を使用しない場合は、次のコードなどの関数を直接使用します.
//        1

function Obj(id1,name1,teststring1)
{
this.id = id1;
this.name = name1;
this.teststring = teststring1;
this.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
}
Obj('006','My Name is obj6','Test Obj6');
sayHello();//id:006@!@name:My Name is obj6@!@teststring:Test Obj6
window.sayHello();//id:006@!@name:My Name is obj6@!@teststring:Test Obj6
console.log(id);//006
console.log(name);//My Name is obj6
console.log(teststring);//Test Obj6
console.log(window.id);//006
console.log(window.name);//My Name is obj6
console.log(window.teststring);//Test Obj6

直接functionを呼び出して、thisポインタはすべてwindowを指して、つまりグローバルオブジェクトで、私は以前1つの言叶を见たことがあります:どこが直接関数を呼び出して、中のthisはすべてグローバルを指します.これはどこでも直接関数を呼び出すと学問があるでしょう.次のコードを見てください.
//         2

function OuterObj(id1,name1,teststring1)
{
this.id = id1;
this.name = name1;
this.teststring = teststring1;
this.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}

function InnerObj(id2,name2,teststring2)
{
this.id = id2;
this.name = name2;
this.teststring = teststring2;
this.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
}

var innerVal = new InnerObj('101','InnerObj','Test InnerObj');//true
console.log(innerVal instanceof InnerObj);
innerVal.sayHello();//id:101@!@name:InnerObj@!@teststring:Test InnerObj

InnerObj('102','InnerObj0','Test InnerObj0');
}

var outObj = new OuterObj('007','My Name is obj7','Test Obj7');
outObj.sayHello();//id:007@!@name:My Name is obj7@!@teststring:Test Obj7
sayHello();//
window.sayHello();//id:102@!@name:InnerObj0@!@teststring:Test InnerObj0
console.log(id);//102
console.log(name);//InnerObj0
console.log(teststring);//Test InnerObj0

このように、関数呼び出しthisが指す方法と関数がwindowを指す、すなわちグローバルオブジェクトであることがわかります.
3.オブジェクトの初期化
オブジェクトの初期化方式は一部の本では字面量方式と呼ばれてオブジェクトを構築していますが、私はオブジェクトの初期化方式が好きです.これはより直感的で、コードは以下の通りです.
//      

var obj = {
id:'008',
name:'My Name is obj8',
teststring:'Test Obj8',
sayHello:function(){
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
};
obj.sayHello();//id:008@!@name:My Name is obj8@!@teststring:Test Obj8
obj['sayHello']();//id:008@!@name:My Name is obj8@!@teststring:Test Obj8
var str = 'sayHello';
obj[str]();//id:008@!@name:My Name is obj8@!@teststring:Test Obj8

この方法は私が比較的に好きなオブジェクトを構築する方法で、javascriptマスター級の人物が空のオブジェクトを構築することを提案したことがあります.var obj={}が望ましいです.この言葉はvar obj={}とvar obj=new Object()を示しています.等価です.var obj={}方式はより簡潔で、o.idを避けた.o.nameなどの煩雑な書き方、jQueryソースコードにはこのような構造オブジェクトの方式が多く使われています.
以上、javascriptでオブジェクトを構築する方法を3つよく知っています.次にjavascript構築オブジェクトの知識を別の角度で理解します.まずjavaのコードを見てみましょう.
public class Obj {

public static String staticParams = " , ";

private String objId = " ";

public String objName = " ";

//
public Obj(){}
}

JAvascriptオブジェクトの属性やメソッドはjavaの思想を使って、クラスに属する属性とメソッド、オブジェクトに属する属性やメソッド、公有属性とメソッド、プライベート属性とメソッドに分けることもできます.
一.クラスに属する属性と方法:オブジェクトで初期化する方式はすべてクラスに属する属性と方法とすることができて、このような定義はjQueryの中で大量に運用します;
二.オブジェクトに属する属性または方法:構造関数でオブジェクトを構築し、thisポインタで指す属性と方法はすべてオブジェクトに属する.
三.公有属性と方法:javascriptの中の属性と方法は生まれながらにして公有である.
四.プライベート属性と方法:これはjavascriptでシミュレーションによって実現されます.このシミュレーションは一般的に役割ドメインの原理を使用します.例えば、1つのfunction内部でvarでオブジェクトを定義し、オブジェクトの役割ドメインは変更function内部に属し、関数外部ではアクセスできません.これがプライベート変数と方法です.
以上のオブジェクトの作成では、中の属性やメソッド操作はオブジェクト固有であり、同じ方法で構築された類似オブジェクトは情報の共有ができないので、類似オブジェクトが情報を共有できるようにするには、prototypeプロトタイプチェーンを使用します.
javascriptには、各関数にprototype属性があります.この属性はポインタであり、オブジェクトを指します.このオブジェクトの用途には、特定のタイプのすべてのインスタンスで共有できる属性と方法が含まれています.
コードは次のとおりです.
//    

function Obj(id1,name1,teststring1)
{
this.id = id1;
this.name = name1;
this.teststring = teststring1;
this.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
}

Obj.prototype.objflag = ' Obj ';
Obj.prototype.proSayHello = function()
{
console.log('Hello World and Obj');
}

var obj1 = new Obj('008','My Name is obj8','Test Obj8');
var obj2 = new Obj('009','My Name is obj9','Test Obj9');

obj1.sayHello();//id:008@!@name:My Name is obj8@!@teststring:Test Obj8
obj2.sayHello();//id:009@!@name:My Name is obj9@!@teststring:Test Obj9
obj1.proSayHello();//Hello World and Obj
obj2.proSayHello();//Hello World and Obj
console.log(obj1.objflag);// Obj
console.log(obj2.objflag);// Obj

prototypeは書くのが煩雑で、覚えにくいです.一般的に多くのインスタンスの共通の属性と方法は固定的で変えにくいので、オブジェクトを初期化する方法で原生チェーンを書くことができます.この考え方はjQueryから学びました.コードは以下の通りです.
//       

function Obj(id1,name1,teststring1)
{
this.id = id1;
this.name = name1;
this.teststring = teststring1;
this.sayHello = function()
{
console.log('id:' + this.id + '@!@name:' + this.name + '@!@teststring:' + this.teststring);
}
}
Obj.prototype = {
objflag:' Obj ',
proSayHello:function(){
console.log('Hello World and Obj');
}
};
var obj1 = new Obj('010','My Name is obj10','Test Obj10');
var obj2 = new Obj('011','My Name is obj11','Test Obj11');

obj1.sayHello();//id:010@!@name:My Name is obj10@!@teststring:Test Obj10
obj2.sayHello();//id:011@!@name:My Name is obj11@!@teststring:Test Obj11
obj1.proSayHello();//Hello World and Obj
obj2.proSayHello();//Hello World and Obj
console.log(obj1.objflag);// Obj
console.log(obj2.objflag);// Obj

はい、このテーマの前半は書き終わりました.前半は主に使用と概念から話して、後半はいくつかの原理といくつかの奇妙な現象の解釈を分析します.