目次
序文
コンピュータープログラミングにおいて、オブジェクトは非常に重要な概念です。これは、データをより適切に整理および管理し、コードをよりモジュール化して再利用可能にするのに役立ちます。オブジェクトには複数のキーと値のペアを格納でき、各キーと値のペアは属性を表し、属性は基本タイプまたは別のオブジェクトの値にすることができます。オブジェクトを通じて、メソッドを定義して呼び出したり、プロパティを操作したり、特定の関数を実装したりできます。
オブジェクト指向プログラミングの考え方は、オブジェクトとクラスを通じてコードを編成および管理し、理解と保守を容易にすることに重点を置いています。実際、問題と解決策をオブジェクトに分解することは非常に自然で直感的な方法であり、コードの再利用とモジュール化を実現するための鍵でもあります。
次の学習では、これらの概念をより深く理解して習得し、小さなケースを通じて学んだ知識を実践して定着させます。一緒に学びの旅に出ましょう!
1. オブジェクトを認識する
1. オブジェクトとは何ですか
-
概念: オブジェクト (オブジェクト) は、属性と値の間のマッピング関係を表す「キーと値のペア」のコレクションです。
-
構文: k と v はコロンで区切られ、k:v の各グループはカンマで区切られ、最後の k:v ペアの後にはカンマは必要ありません
- オブジェクトのプロパティ キー名が JS 識別子の命名規則に準拠していない場合は、キー名を引用符で囲む必要があります
- 例:
'favorite-book':'舒克和贝塔'
属性名にダッシュがあり、]S 識別子の命名規則に準拠していないため、属性名を引用符で囲む必要があります。
-
オブジェクトのプロパティへのアクセス
-
「ドット構文」を使用して、オブジェクト内の指定されたキーの値にアクセスできます。
xiaoming.name;//小明 xiaoming.age;//12 xiaoming.hobbys;//['足球',游泳','编程]
-
属性名が ]S 識別子の命名規則に準拠していない場合は、角かっこを使用して
アクセスする必要がありますxiaoming['favorite-book'];//舒克和贝塔
-
属性名を変数として保存する場合は、角括弧で囲む必要があります
var obj = { a:1, b:2, C:3 }; //属性名用变量存储 var key ='b'; console.log(obj.key); //undefined console.log(obj[key]);//2
-
-
財産の変化
- 代入演算子を直接使用してプロパティを再代入し、プロパティを変更します。
var obj ={ a:10 } obj.a = 30; //将obj里a的值改成了30 ob].a++; // a = 31
- 代入演算子を直接使用してプロパティを再代入し、プロパティを変更します。
-
属性の作成
- オブジェクト自体にプロパティ値がない場合、ドット構文を使用して値を割り当てるときにプロパティが作成されます。
var obj ={ a:10 }; obj.b = 40; //在obj对象中创建了b:40这个键值对
- オブジェクト自体にプロパティ値がない場合、ドット構文を使用して値を割り当てるときにプロパティが作成されます。
-
プロパティの削除
-
オブジェクトのプロパティを削除したい場合は、delete 演算子を使用する必要があります。
var obj = { a:1, b:2 }; delete obj.a;
-
2. オブジェクトメソッド
-
プロパティ値が関数の場合、オブジェクトの「メソッド」とも呼ばれます。
varxiaoming = { sayHello:function(){ //sayHello方法 console.log('你好,我是小明,今年12岁,我是个男生'); } }
-
ドットメソッドを使用した関数の呼び出し
xiaoming.sayHello();
-
メソッドも function ですが、メソッドはオブジェクトの「関数属性」であり、オブジェクトによって呼び出される必要があります。
3. オブジェクトトラバーサル
- for ... in ...ループを使用すると、オブジェクトの各キーを反復処理できます。
4. オブジェクトのディープおよびシャロークローン作成
- オブジェクトが参照型の値の場合
var obj1 = obj2
このような構文を使用してオブジェクトのクローンを作成することはできません- == または === を使用してオブジェクトを比較する場合、比較は比較値が同じかどうかではなく、メモリ内の同じオブジェクトであるかどうかです。
- 浅いクローン
- オブジェクトの浅いクローン作成は、for ...in...サイクルを使用して実現できます。
- ディープクローン
-
配列のタイプと同様に、オブジェクトのディープ クローン作成には再帰の使用が必要です。
var obj1 = { a:1, b:2, c:[33,44,{ m:55, n:66, p:[77,88] }] }; // 定义一个深克隆函数 function deepClone(o){ // 判断o是对象还是数组,必须先判断是不是数组,因为数组的类型也是对象 if(Array.isArray(o)){ //数组 var result = []; for(var i=0;i < o.length;i++){ result.push(deepClone(o[i])); } }else if(typeof o == 'object'){ // 对象 var result = { }; for (var k in o){ result[k] = deepClone(o[k]) } }else{ //基本类型值 var result = o; } return result; } var obj2 = deepClone(obj1); console.log(obj2); // 测试一下 console.log(obj1 === obj2); //false obj1.c.push(99); console.log(obj2); //obj2是不变的,因为没有'藕断丝连'的现象
-
2. 関数のコンテキストを理解する
-
関数のコンテキスト (このキーワード)は呼び出しメソッドによって決まります。同じ関数が異なる形式で呼び出され、関数のコンテキストも異なります。
var xiaoming = { nickname:小明, age:12, sayHello = function (){ console..log('我是'+this.nickname+',我'+this.age+'岁了); } };
-
シナリオ 1: 関数はオブジェクト dot によって呼び出され、関数内の this はドット付きオブジェクトを参照します。
xiaoming.sayHello();
-
ケース 2: 括弧は関数を直接呼び出し、関数内の this はウィンドウ オブジェクトを参照します。
var sayHello = xiaoming.sayHello; sayHello();
-
-
関数は「ランタイムコンテキスト」戦略です
-
関数が呼び出されない場合、関数のコンテキストを決定できません。
1. 関数のコンテキストルール★
-
ルール①
- オブジェクトドットがそのメソッド関数を呼び出すと、関数のコンテキストはドットオブジェクトになります。
对象.方法();
-
ルール②
- 括弧は関数を直接呼び出し、関数のコンテキストはウィンドウ オブジェクトです。
函数();
-
ルール③
- 配列 (配列のようなオブジェクト) は呼び出す関数を列挙し、コンテキストはこの配列 (配列のようなオブジェクト) です。
- 配列状オブジェクトとは: キー名が自然数(0から始まる)の列であり、長さ属性を持つオブジェクト
- 引数オブジェクトは最も一般的な配列のようなオブジェクトで、関数の実際のパラメータ リストです。
数组[下标]();
- 配列 (配列のようなオブジェクト) は呼び出す関数を列挙し、コンテキストはこの配列 (配列のようなオブジェクト) です。
-
ルール④
-
IIFE の関数、コンテキストはウィンドウ オブジェクトです
(function(){ })();
-
-
ルール⑤
- タイマーとディレイラーは関数を呼び出し、コンテキストはウィンドウ オブジェクトです
setInterval(函数,时间);
setTimeout(函数,时间);
-
ルール⑥
- イベント ハンドラーのコンテキストは、イベントがバインドされる DOM 要素です。
DOM元素.onclick=function(){ }
- イベント ハンドラーのコンテキストは、イベントがバインドされる DOM 要素です。
2.電話して応募する★
- call と apply は関数のコンテキストを指定できます
函数.ca11(上下文);
パラメータをカンマでリストするには函数.apply(上下文);
パラメータを配列に書き込むには
3. コンストラクター
1. new 演算子を使用して関数を呼び出します。
-
「4つのステップ」
- 1) 関数本体に空のオブジェクトが自動的に作成されます
- 2) 関数のコンテキスト (this) はこのオブジェクトを指します。
- 3) 関数本体内のステートメントが実行されます
- 4) 関数に return ステートメントがない場合でも、関数は自動的にコンテキスト オブジェクトを返します。
2. クラスとインスタンス
3. コンストラクターと「クラス」
-
Java、C++などは「オブジェクト指向」(オブジェクト指向)言語です
-
JavaScript は「オブジェクトベース」の言語です
-
JavaScript のコンストラクターは、 OO 言語の「クラス」に似ており、記述方法は確かに似ていますが、それでも実際の OO 言語とは根本的に異なります。
4. プロトタイプとプロトタイプチェーン
1.試作・試作チェーン検索★
- どの関数にもプロトタイプ属性があり、プロトタイプとは「プロトタイプ」を意味します。
- プロトタイプ プロパティの値はオブジェクトであり、デフォルトでは関数を指すコンストラクター プロパティを持ちます。
- 通常の関数のprototype属性は役に立ちませんが、コンストラクタのprototype属性は非常に便利です
- コンストラクターのプロトタイプ プロパティは、そのインスタンスのプロトタイプです。
console.log(xiaoming.__proto__ === People.prototype); //true
- コンストラクターのプロトタイプ プロパティは、そのインスタンスのプロトタイプです。
- プロトタイプチェーンのルックアップ
- JavaScript では、インスタンスがそのプロトタイプのプロパティとメソッドにアクセスできることが規定されています
- hasOwnProperty() メソッド
- オブジェクトが実際にプロパティまたはメソッドを「所有」しているかどうかを確認できます
- 演算子内
- 特定のプロパティまたはメソッドがオブジェクトからアクセスできるかどうかのみを確認でき、それが独自のプロパティまたはメソッドであるかどうかを確認することはできません。
2. プロトタイプにメソッドを追加する
- インスタンスにメソッドを直接追加するデメリット: 各インスタンスと各インスタンスのメソッド関数はメモリ内で異なる関数となるため、メモリが無駄に消費されます。
- 解決策:プロトタイプにメソッドを追加します。
3. プロトタイプチェーンの終わり
- あらゆるもののプロトタイプチェーンの終わり - Object.prototype
-
コード例
function People(){ } var xiaoming = new People(); console.log(xiaoming.__proto__.__proto__ === Object.prototype); //true console.log(Object.prototype.__proto__); //null console.log(Object.prototype.hasOwnProperty('hasOwnProperty')); //true
-
配列のプロトタイプチェーン
var arr = [22,33,4,555];
console.log(arr.__proto__ === Array.prototype); //true
console.log(arr.__proto__ .__proto__=== Object.prototype); //true
console.log(Array.prototype.hasOwnProperty('push')); //true
4.継承★
-
継承は 2 つのクラス間の「ある種の」関係を表します。たとえば、学生は「ある種の」人であるため、人間と学生クラスの間に継承関係が形成されます。
-
People は「親クラス」(または「スーパークラス」、「基本クラス」)、Student は「サブクラス」(または「派生クラス」)です。
-
サブクラスは親クラスを強化し、クラスの説明をより具体的かつ詳細なものにします。
-
例
- プロトタイプチェーンによる継承
- サブクラス コンストラクターのプロトタイプが親クラスのインスタンスを指すようにします。
Student.prototype = new People();
- サブクラス コンストラクターのプロトタイプが親クラスのインスタンスを指すようにします。
//父类:人类
function People(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
People.prototype.sayHello = function (){
console.log('你好,我是'+this.name +'我今年'+this.age+'岁了');
}
People.prototype.sleep = function (){
console.log(this.nam+'开始睡觉,zzzz');
}
// 子类:学生
function Student(name,age,sex,school,studentNumber){
this.name = name;
this.age = age;
this.sex = sex;
this.school = school;
this.studentNumber = studentNumber;
}
//关键语句,实现继承
Student.prototype = new People();
Student.prototype.study = function (){
console.log(this.name + '正在学习');
}
Student.prototype.exam = function (){
console.log(this.name+'正在考试,加油!');
}
//实例化
var hanmeimei = new Student('韩梅梅',12,'女','CSDN大学',123456);
hanmeimei.study();
hanmeimei.sayHello();
5、オブジェクト指向への移行
- オブジェクト指向の本質:さまざまなクラスを定義し、そのクラスのインスタンスを動作させる
- オブジェクト指向の利点:より明確なプログラム記述、より緊密なコード構造、より堅牢なコード、および容易なメンテナンス
- オブジェクト指向がよく使われる場面:カプセル化や再利用性が必要な場面(コンポーネント思考)
1. 信号機の小型ケース
-
オブジェクト指向プログラミングを使用すると、競合する多数の信号機の問題を「コンポーネント」思考で解決できます
-
オブジェクト指向プログラミング、最も重要なことはクラスを書くことです
-
TrafficLight クラス
- 属性:独自の現在の色 color、独自の DOM 要素 dom
- メソッド: init()の初期化、色の切り替え(changeColor)、バインドイベントのbindEvent()
-
コード例:
#box img{ width: 80px ; }
<div id="box" ></div>
//定义红绿灯类,构造函数 function TrafficLight(){ //颜色属性,一开始都是红色 //红色1,黄色2,绿色3 this.color = 1; //调用自己的初始化方法 this.init(); //绑定监听 this.bindEvent(); } //初始化方法 TrafficLight.prototype.init = function (){ // alert('我是init方法'); //创建自己的DOM this.dom = document.createElement('img'); this.dom.src = this.color+'.jpg'; box.appendChild(this.dom); } // 绑定监听 TrafficLight.prototype.bindEvent = function (){ //备份上下文,这里的this指的是JS实例 var self = this; //当自己的dom被点击时 this.dom.onclick = function (){ // 当被点击时,调用自己的changeColor方法 self.changeColor(); }; } // 改变颜色 TrafficLight.prototype.changeColor = function (){ // 改变自己的color属性,从而有一种"自治"的感觉,自己管理自己不干扰别的红绿灯 this.color++; if(this.color == 4){ this.color = 1; } // 光color属性变化没用,还要更改自己的dom中src属性,才能更换图片 this.dom.src = this.color+'.jpg'; }; // 得到盒子 var box = document.getElementById('box'); // 实例化100个 var count = 100; // 当count-- 为0的时候,判断为false,跳出循环 while(count--){ new TrafficLight(); }
2. カラフルな小さなボールケース
-
Boll クラスのプロパティ
-
Boll クラスのメソッド
- init() 初期化メソッド
- update() 更新メソッド
-
複数の小さなボールのアニメーションを実現
- 各ボールのインスタンスを同じ配列に配置します
- [{ボール インスタンス},{ボール インスタンス},{ボール インスタンス},{ボール インスタンス}]
- タイマーを使用して各フレーム内の各ボールを移動し、その更新メソッドを呼び出すだけです。
- 各ボールのインスタンスを同じ配列に配置します
-
コード例:
body{ background-color: black; } .ball{ position: absolute; border-radius: 50%; }
//小球类 function Ball(x,y){ //属性x,y表示的是圆心的坐标 this.x = x; this.y = y; //透明的 this.opacity = 1; do{ // 这个小球的x增量和y的增量 this.dX = parseInt(Math.random()*20)-10; this.dY = parseInt(Math.random()*20)-10; }while(this.dX === 0 || this.dY === 0) // 小球的背景颜色 this.color = colorArr[parseInt(Math.random()*colorArr.length)]; // 小球半径 this.r = 20; // 初始化 this.init(); // 把自己推入数组,注意:这里的this不是类本身,而是实例 ballArr.push(this); } Ball.prototype.init = function (){ //创建自己的dom this.dom = document.createElement('div'); this.dom.className = 'ball'; this.dom.style.width = this.r *2 +'px'; this.dom.style.height = this.r *2 +'px'; this.dom.style.left = this.x - this.r+'px'; this.dom.style.top = this.y - this.r+'px'; this.dom.style.backgroundColor = this.color; //上树 document.body.appendChild(this.dom); } // 更新 Ball.prototype.update = function (){ // 位置改变 this.x += this.dX; this.y -= this.dY; // 半径改变 this.r += 0.2; // 透明度改变 this.opacity -= 0.05; this.dom.style.width = this.r *2 +'px'; this.dom.style.height = this.r *2 +'px'; this.dom.style.left = this.x - this.r+'px'; this.dom.style.top = this.y - this.r+'px'; this.dom.style.opacity = this.opacity; // 当透明度小于0,就需要从数组中删除自己,DOM元素也要删除自己 if(this.opacity<0){ //从数组中删除自己 for (var i = 0; i<ballArr.length;i++){ if(ballArr[i] == this){ ballArr.splice(i,1); } //还要删除自己的dom document.body.removeChild(this.dom); } } }; // 把所有的小球实例都放到一个数组中 var ballArr = []; // 初始颜色数组 var colorArr = ['#66CCCC','#CCFFCC','#FF99CC','#FF6666','#CC3399','#ff6600'] // 定时器,负责更新所有的小球实例 setInterval(function (){ //遍历数组 ,调用update方法 for(var i= 0;i<ballArr.length;i++){ ballArr[i].update(); } },20); // 鼠标指针的监听 document.onmousemove = function (e){ //得到鼠标指针的位置 var x = e.clientX; var y = e.clientY; new Ball(x,y); }
6、JS 組み込みオブジェクト
1. 包装
- Number()、String()、および Boolean() のインスタンスはすべてオブジェクト型であり、それらの Primitivevalue プロパティには独自の値が格納されます。
- new からの基本型の値は通常、操作に参加できます。
- ラッパー クラスの目的は、基本型の値がコンストラクターのプロトタイプからメソッドを取得できるようにすることです。
2.数学オブジェクト★
-
べき乗と平方根: Math.pow()、Math.sqrt()
-
切り上げと切り捨て: Math.ceil()、Math.floor()
-
Math.round() メソッド:丸め
- 小数点以下第 2 位に四捨五入
- 小数点以下第 2 位に四捨五入
-
Math.max(): パラメータリストの最大値を取得します。
- Math.max() を使用して配列の最大値を見つける
-
Math.max() では、パラメータが配列ではなく「リスト」されている必要があります。
-
apply メソッドを使用すると、関数のコンテキストを指定し、「散乱値」を関数のパラメーターとして配列の形式で渡すことができます。
var arr = [3,6,9,2]; var max = Math.max.apply(null,arr); console.log(max); // 9
-
- Math.max() を使用して配列の最大値を見つける
-
Math.min(): パラメータリストの最小値を取得します。
-
Math.random(): 0 から 1 までの小数を取得します。
- 区間 [a,b] の整数を取得するには、次の式を使用できます。
- parseInt(Math.random()*(ba +1))+a
- 区間 [a,b] の整数を取得するには、次の式を使用できます。
3.日付オブジェクト★
- new Date() を使用して、オブジェクト型の値である現在の時刻の日付オブジェクトを取得します。
- new Date(2023,6,26) を使用して、指定した日付の日付オブジェクトを取得します。
- 2 番目のパラメータは 0 から始まる月を表し、6 は 7 月を表すことに注意してください。
- new Date('2023-07-26') と書くこともできます。
- new Date(2023,6,26) を使用して、指定した日付の日付オブジェクトを取得します。
- 日付オブジェクトの共通メソッド
- タイムスタンプ
-
タイムスタンプは、1970 年 1 月 1 日の午前 0 時のある時点からのミリ秒数を表します。
-
日付オブジェクトは、getTime() メソッドまたは Date.parse() 関数によってタイムスタンプに変換できます。
-
新しいDate(タイムスタンプ)を書き込むことで、タイムスタンプを日付オブジェクトに変更できます
-
7. 継承と組み込みコンストラクター [展開]
-
組み込みコンストラクター
- JavaScript には多くの組み込みコンストラクターがあります。たとえば、Arrayは配列型のコンストラクター、Functionは関数型のコンストラクター、Objectはオブジェクト型のコンストラクターです。
- 組み込みコンストラクターは非常に便利です。この型のすべてのメソッドは、その組み込みコンストラクターのプロトタイプで定義されています。このオブジェクトに新しいメソッドを追加して、特定の型の機能を拡張できます。
- Number\String\Boollearn は、3 つの基本型の値のラッパー クラスです。new で呼び出すと、基本型の値の「オブジェクト」バージョンを生成できます。
-
組み込みコンストラクターの関係
- オブジェクトを含むあらゆる関数を関数「new」とみなすことができます。
- オブジェクトを含むあらゆる関数を関数「new」とみなすことができます。
-
コンストラクターを使用する場合(「偽のオブジェクト」または「古典的な継承」とも呼ばれます)
- 利点: プロトタイプに含まれる参照型の値によって引き起こされる問題と、サブクラス コンストラクターの不適切な問題を解決します。
- 原則:サブクラス コンストラクター内でスーパークラス コンストラクターを呼び出しますが、コンテキストをバインドするために call() を使用することに注意してください。
function People(name,sex,age){ this.name = name; this.sex = sex; this.age = age; this.arr = [22,33,44]; } function Student(name,sex,age,school,sid){ People.call(this,name,sex,age); // 借助构造函数 this.school = school; this.sid = sid; } var xiaoming = new Student('小明','男',12,'CSDN学校',123455); console.log(xiaoming); </script>
-
構成の継承 (最も一般的に使用される)
- 原則: プロトタイプチェーンを借用する技術とコンストラクターを借用する技術を組み合わせたもので、擬似古典継承とも呼ばれます。
- 欠点: いずれの場合も、スーパークラスのコンストラクターは 2 回呼び出されます。1 回はサブクラスのプロトタイプの作成時、もう 1 回はサブクラスのコンストラクター内で呼び出されます。
//父类 function People(name,sex,age){ this.name = name; this.sex = sex; this.age = age; } People.prototype.sayHello = function (){ console.log('你好,我是'+this.name+'今年'+this.age+'岁了'); } People.prototype.sleep = function (){ console.log(this.name+'正在睡觉'); } //子类 function Student(name,sex,age,school,sid){ //借助构造函数 People.call(this,name,sex,age); this.school = school; this.sid = sid; } //实现继承:借助原型链 Student.prototype = new People(); Student.prototype.exam = function (){ console.log(this.name + '正在考试') } Student.prototype.sayHello = function (){ console.log('敬礼!你好,我是'+this.name+'今年'+this.age+'岁了'+this.school+'的学生'); } var xiaoming = new Student('小明','男',12,'CSDN学校',123455); console.log(xiaoming); xiaoming.sayHello(); xiaoming.sleep(); xiaoming.exam();
-
プロトタイプの継承
- Object.creat() の紹介
- IE9 以降では、コンストラクターに頼らずに、指定されたオブジェクトに基づいてプロトタイプとして新しいオブジェクトを作成できるObject.create() メソッドのサポートが開始されました。
- 例:
var obj2 = Object.create(obj1);
- 概念: コンストラクターを作成する必要はなく、新しいオブジェクトを既存のオブジェクトに「類似」させるだけの場合は、プロトタイプ継承と呼ばれる Object.create() を使用できます。
- Object.creat() の紹介
-
寄生継承
- パラメーター o を受け取り、プロトタイプとして o を持つ新しいオブジェクト p を返し、事前に作成された新しいメソッドを p に追加する関数を作成します。
- 寄生継承とは、「オブジェクトを強化」できる関数を記述することです。オブジェクトがこの関数に渡される限り、関数はこのオブジェクトに基づいて新しいオブジェクトを作成し、新しいプリセット メソッドを新しいオブジェクトに割り当てます。
- 寄生継承は、カスタム型やコンストラクターではなくオブジェクトが主に考慮される場合にも便利なパターンです。
- 欠点: 寄生継承を使用してオブジェクトに関数を追加すると、関数の再利用ができないため効率が低下します。つまり、「メソッドがプロトタイプに記述されていない」ためです。
- パラメーター o を受け取り、プロトタイプとして o を持つ新しいオブジェクト p を返し、事前に作成された新しいメソッドを p に追加する関数を作成します。
-
寄生組成の継承
- コンストラクターを借用してプロパティを継承する
- プロトタイプチェーンのハイブリッド形式によるメソッドの継承
- 基本的な考え方: サブタイプのプロトタイプを指定するためにスーパータイプのコンストラクターを呼び出す必要はありません。必要なのはスーパータイプのプロトタイプのコピーだけです。基本的に、寄生継承を使用してスーパータイプのプロトタイプを継承し、その結果をサブタイプのプロトタイプに割り当てます。
-
インスタンス演算子
- instanceof 演算子は、次のように「オブジェクトが特定のクラスのインスタンスであるかどうか」を検出するために使用されます。
- 基礎となるメカニズム: Student.prototype 属性が xiaoming のプロトタイプ チェーン上にあるかどうかを確認します(存在する限り、何層でも問題ありません)。