目次
JavaScript はい: オブジェクト リテラル形式、またはオブジェクト コンストラクターを使用します
1 var person = new Object();2   person.name = "jack";3   person.sayName = function () {4   alert(this.name)5 }
ログイン後にコピー
" >
1 var person = new Object();2   person.name = "jack";3   person.sayName = function () {4   alert(this.name)5 }
ログイン後にコピー
1 var person = {2   name: "jack";3   sayName: function () {4     alert(this.name)5   }6 }
ログイン後にコピー
" >
1 var person = {2   name: "jack";3   sayName: function () {4     alert(this.name)5   }6 }
ログイン後にコピー
ファクトリーパターンを簡単に理解すると、ファクトリー: 「私はオブジェクトを作成し、作成プロセス全体に責任を負いますが、タスクが完了した後は、私はそれとは何の関係もありません。O ( ∩_∩)おはは〜”
これは関数です。私は特定の型のオブジェクト インスタンスのみを作成し、それ以外のことは気にしません (ここにはすでに型の概念があることに気づきましたか、小さなグループのように感じられます)
コンストラクタを作成すると(通常の関数も同様です)`prototype`(プロトタイプ)が自動生成されます コンストラクターと`prototype`は1対1の関係にあります。今回は `prototype` にあります `constructor` 属性は 1 つだけです (明らかに別の `__proto__` があります。これについてはここでは説明しません。後で説明します)
组合使用构造函数模式和原型模式
动态原型模式
寄生构造函数模式
稳妥构造函数模式
结语
ホームページ ウェブフロントエンド jsチュートリアル JS オブジェクトを作成する一般的な方法は何ですか?

JS オブジェクトを作成する一般的な方法は何ですか?

Jun 28, 2017 am 09:55 AM
javascript 原理 方法

はじめに

「js言語ではすべてがオブジェクトである」という言葉があるように、オブジェクトを作成する方法はたくさんありますので、今日は最も簡単な方法を整理します

JavaScript はい: オブジェクト リテラル形式、またはオブジェクト コンストラクターを使用します

オブジェクト リテラル形式

1 var person = new Object();2   person.name = "jack";3   person.sayName = function () {4   alert(this.name)5 }
ログイン後にコピー

オブジェクト コンストラクターを使用します

1 var person = {2   name: "jack";3   sayName: function () {4     alert(this.name)5   }6 }
ログイン後にコピー

明らかな欠点: 複数のオブジェクトを作成する場合、コードの重複が発生するため、「ファクトリー パターン」が登場しました

ファクトリーパターン

ファクトリーパターンを簡単に理解すると、ファクトリー: 「私はオブジェクトを作成し、作成プロセス全体に責任を負いますが、タスクが完了した後は、私はそれとは何の関係もありません。O ( ∩_∩)おはは〜”

 1 function createPerson (name) { 2   var o = new Object(); 3   o.name = name; 4   o.sayName = function () { 5     alert(this.name) 6   } 7   return o 8 } 9 10 var p1 = new createPerson("jack");
ログイン後にコピー
明らかな欠点: すべてのオブジェクト インスタンスは `Object` 型であり、型の区別はほとんどありません。タイプを区別できないと言うなら、私は信じません。次に、コードを見てみましょう:

1 var p1 = new createPerson("jack");2 var p2 = new createPerson("lucy");3 4 console.log(p1 instanceof Object); //true5 console.log(p2 instanceof Object); //true
ログイン後にコピー
ほら、これは事実ですか? この問題を解決するには、「コンストラクター パターン」を使用します

コンストラクター パターン

これは関数です。私は特定の型のオブジェクト インスタンスのみを作成し、それ以外のことは気にしません (ここにはすでに型の概念があることに気づきましたか、小さなグループのように感じられます)

 1 function Person (name) { 2   this.name = name; 3   this.sayName = function () { 4     alert(this.name) 5   } 6 } 7  8 function Animal (name) { 9   this.name = name;10   this.sayName = function () {11     alert(this.name)12   }13 }14 15 var p1 = new Person("jack")16 p1.sayName() //"jack"17 18 var a1 = new Animal("doudou")19 a1.sayName() //"doudou"20 21 console.log(p1 instanceof Person) //true22 console.log(a1 instanceof Animal) //true23 console.log(p1 instanceof Animal) //false(p1显然不是Animal类型,所以是false)24 console.log(a1 instanceof Person) //false(a1也显然不是Person类型,所以同样是false)
ログイン後にコピー
上記のコードは次のことを証明します。コンストラクター パターンは実際にオブジェクトの種類を区別できます。では、このモデルは完璧なのでしょうか? しかし、そうではありません。次のコードを見てみましょう:

1 //接着上面的代码2 console.log(p1.sayName === a1.sayName) //false
ログイン後にコピー
問題は見つかりましたか? 「p1」の「sayName」は「a1」の「sayName」と同じではありません。これは何を意味しますか? 「コンストラクター パターン」には「パブリック」という概念がまったくなく、作成された各オブジェクト インスタンスには独自のプロパティとメソッドのセットがあることは理解できますが、メソッドを実行する必要があります。明らかな欠点: 上で説明したように、この問題を解決するために、新しいモード「プロトタイプ モード」が登場しました。このモードは単にステージをジャンプするだけです。以下で「プロトタイプ パターン」を見てみましょう

プロトタイプ パターン

ここで覚えておくべきことが 1 つあります。コンストラクター内のプロパティとメソッドは各オブジェクト インスタンス間で共有されず、すべて個別に設定されます。共有を実現したい場合は、コンストラクターのプロトタイプにプロパティやメソッドを格納する必要があります。この文はどういう意味ですか?以下、詳しく説明していきます

コンストラクタを作成すると(通常の関数も同様です)`prototype`(プロトタイプ)が自動生成されます コンストラクターと`prototype`は1対1の関係にあります。今回は `prototype` にあります `constructor` 属性は 1 つだけです (明らかに別の `__proto__` があります。これについてはここでは説明しません。後で説明します)


この `constructor` とは何ですか?これは、`プロトタイプ` のコンストラクターを指す、ポインターに似た参照であり、ポインターはデフォルトで存在する必要があります

1 console.log(Person.prototype.constructor === Person) //true
ログイン後にコピー

先ほど、`プロトタイプ` は `自動生成` だと言いましたが、実際には存在しません。これは、`prototype` を手動で生成するもう 1 つの方法です:
1 function Person (name) {2   this.name = name3 }4 Person.prototype = {5   //constructor: Person,6   age: 307 }8 console.log(Person.prototype) //Object {age: 30}9 console.log(Person.prototype.constructor === Person) //false
ログイン後にコピー

ヒント: `prototype` がコンストラクターに対して手動で作成できることを証明するために、ここでは `name` 属性が `prototype` に追加されています。
次のコード行に問題があることに気づいたかもしれません:

1 console.log(Person.prototype.constructor === Person) //false
ログイン後にコピー

結果が `false` なのはなぜですか?兄さん、先ほどの「プロトタイプ」はデフォルトで生成されたものですが、別の方法、つまり手動設定を使用しました。手動設定の原理を詳しく分析してみましょう:
1. コンストラクターの `prototype` は実際にはオブジェクトです


2. `prototype` をこのように設定すると、元の `person.prototype` は実際には次のようになります。その後、別のオブジェクトが再度参照されます

3. このとき、コンストラクターは `prototype` を見つけることができますが、 `prototype` はコンストラクターを見つけることができません

1 Person.prototype = {2   //constructor: Person, // 因为constructor属性,我没声明啊,prototype就是利用它来找到构造函数的,你竟然忘了声明3   age: 304 }
ログイン後にコピー

4.コンストラクターの手動設定 関数間の接続を失わずに関数のプロトタイプを設定するには、次のようにします:
1 function Person (name) {2   this.name = name3 }4 Person.prototype = {5   constructor: Person, //constructor一定不要忘了!!6   age: 307 }
ログイン後にコピー

画外音:“说到这里,你还没有讲原型模式是如何实现属性与方法的共享啊”,不要急,马上开始:

对象实例-构造函数-原型,三者是什么样的关系呢?

看明白这张图的意思吗?
1.当对象实例访问一个属性时(方法依然),如果它自身没有该属性,那么它就会通过`__proto__`这条链去构造函数的`prototype`上寻找
2.构造函数与原型是一对一的关系,与对象实例是一对多的关系,而并不是每创建一个对象实例,就相应的生成一个`prototype`
这就是原型模式的核心所在,结论:在原型上声明属性或方法,可以让对象实例之间共用它们

然后原型模式就是完美的吗?并不是,它有以下两个主要问题:
问题1:如果对象实例有与原型上重名的属性或方法,那么,当访问该属性或方法时,实例上的会屏蔽原型上的

1 function Person (name) {2   this.name = name3 }4 Person.prototype = {5   constructor: Person,6   name: 'lucy'7 }8 var p1 = new Person('jack');9 console.log(p1.name); //jack
ログイン後にコピー

问题2:由于实例间是共享原型上的属性和方法的,所以当其中一个对象实例修改原型上的属性(基本值,非引用类型值或方法时,其他实例也会受到影响


原因就是,当实例自身的基本值属性与原型上的重名时,实例就会创建该属性,留着今后自己使用,而原型上的属性不会被修改;但如果属性是引用类型值,如:`Array`、`Object`,当发生重名时,实例是不会拷贝一份新的留给自己使用的,还是坚持实例间共享,所以就会出现上图中的情况

以上两个问题就是原型模式的明显缺点,为了改掉这些缺点,我们一般会采用一种组合模式“组合使用构造函数模式和原型模式”,其实在原型模式这一节,该模式已经有所应用了

组合使用构造函数模式和原型模式

这种模式可谓是集构造函数模式和原型模式之所长,用构造函数模式来定义对象实例的属性或方法,而共享的属性或方法就交给原型模式

 1 function Person (name) { 2   this.name = name //实例的属性,在构造函数中声明 3 } 4  5 Person.prototype = { 6   constructor: Person, 7   sayName: function () { //共享的方法存在原型中 8     alert(this.name) 9   }10 }
ログイン後にコピー

注:此模式目前是ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法

-----------------

下面要介绍的几个模式是针对不同场景的,而不是说`组合使用构造函数模式和原型模式`有什么缺点,又用这几个模式来弥补,不是这样的

动态原型模式

特点:共享的方法是在构造函数中检测并声明的,原型并没有被显示创建

 1 function Person (name) { 2   this.name = name; 3   if (typeof this.sayName !== 'function') { //检查方法是否存在 4     console.log('sayName方法不存在') 5     Person.prototype.sayName = function () { 6       alert(this.name) 7     } 8   } else { 9     console.log('sayName方法已存在')10   }11 }12 13 var p1 = new Person('jack'); //'sayName方法不存在'14 p1.sayName(); //因为sayName不存在,我们来创建它,所以这里输出'jack'15 var p2 = new Person('lucy'); //'sayName方法已存在'16 p2.sayName(); //这时sayName已存在,所以输出'lucy'
ログイン後にコピー

当`Person`构造函数第一次被调用时,`Person.prototype`上就会被添加`sayName`方法;《Javascript高级程序设计》一书说到:使用动态原型模式时,不能使用对象字面量重写原型。我们来理解一下:

 

分析:
1.`p1`实例创建,此时原型没有`sayName`方法,那我们就为原型添加一个
2.随后,我们以字面量的形式重写了原型,这时旧的原型并没有被销毁,而且它和`p1`还保持着联系
3.之后的实例,也就是这里的`p2`,都是与新原型保持联系;所以`p1`、`p2`有各自的构造器原型,即使它们的构造器是同一个

所以切记:当我们采用动态原型模式时,千万不要以字面量的形式重写原型

寄生构造函数模式

了解此模式之前,我们先来想一个问题:构造函数为什么要用`new`关键字调用?代码说话:

我们发现什么?如果不是`new`方法调用构造函数,那么就要显式的`return`,否则构造函数就不会有返回值;但如果使用`new`,那就没有这个问题了

下面我们再来看寄生构造函数模式:

 1 function Person (name) { 2   var o = new Object(); 3   o.name = name; 4   o.sayName = function () { 5     alert(this.name) 6   }; 7   return o 8 } 9 10 var p1 = new Person('jack'); //与工厂模式唯一不同之处:使用new调用11 p1.sayName(); //jack
ログイン後にコピー

其实new不new都无所谓,因为我们已经显式的return o

那么寄生构造函数模式到底有什么应用场景呢?据《javascript高级程序设计》一书记载,举例:如果我们想创建一个具有额外方法的特殊数组,那么我们可以这样做:

 1 function SpecialArray () { 2   var values = new Array(); 3   Array.prototype.push.apply(values,arguments); 4     values.toPipedString = function () { 5     return this.join('|') 6   } 7   return values 8 } 9 10 var colors = new SpecialArray('red','blue','green');11 alert(colors.toPipedString()) //'red|blue|green'
ログイン後にコピー

最后重要的一点:该模式和构造函数和原型无缘,也就是不能区分实例类型,因为该模式生成的实例,它的构造函数都是Object,原型都是Object.prototype

稳妥构造函数模式

该模式与寄生构造函数相比,主要有两点不同:
1.创建对象实例的方法不引用this
2.不使用new操作符调用构造函数
按照稳妥构造函数的要求,可以将前面的Person构造函数重写如下:

1 function Person (name) {2   var o = new Object();3   o.sayName = function () {4     alert(name) //这里其实涉及到了闭包的知识,因此产生了私有属性的概念5   }6   return o7 }
ログイン後にコピー

此模式最适合在一些安全的环境中(这些环境中会禁止使用this和new),同理,此模式与构造函数和原型也无缘

结语

以上就是对js中创建对象的方式的总结,希望对大家有所帮助

以上がJS オブジェクトを作成する一般的な方法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

nohupの機能と原理の解析 nohupの機能と原理の解析 Mar 25, 2024 pm 03:24 PM

nohup の役割と原理の分析 Unix および Unix 系オペレーティング システムでは、nohup はバックグラウンドでコマンドを実行するためによく使用されるコマンドです。ユーザーが現在のセッションを終了したり、ターミナル ウィンドウを閉じたりしても、コマンドはまだ実行され続けています。この記事では、nohup コマンドの機能と原理を詳しく分析します。 1. nohup の役割: バックグラウンドでのコマンドの実行: nohup コマンドを使用すると、ターミナル セッションを終了するユーザーの影響を受けることなく、長時間実行されるコマンドをバックグラウンドで実行し続けることができます。これは実行する必要があります

Struts フレームワークの原則と実践についての深い議論 Struts フレームワークの原則と実践についての深い議論 Feb 18, 2024 pm 06:10 PM

Struts フレームワークの原理分析と実践的な調査 JavaWeb 開発で一般的に使用される MVC フレームワークとして、Struts フレームワークは優れた設計パターンとスケーラビリティを備えており、エンタープライズ レベルのアプリケーション開発で広く使用されています。この記事では、Struts フレームワークの原理を分析し、読者がフレームワークをよりよく理解して適用できるように、実際のコード例を使用してそれを検討します。 1. Struts フレームワークの原理の分析 1. MVC アーキテクチャ Struts フレームワークは MVC (Model-View-Con) に基づいています。

MyBatis のバッチ挿入実装原理の深い理解 MyBatis のバッチ挿入実装原理の深い理解 Feb 21, 2024 pm 04:42 PM

MyBatis は、さまざまな Java プロジェクトで広く使用されている人気のある Java 永続層フレームワークです。その中でも、バッチ挿入は、データベース操作のパフォーマンスを効果的に向上させることができる一般的な操作です。この記事では、MyBatis でのバッチ挿入の実装原理を深く調査し、特定のコード例を使用して詳細に分析します。 MyBatis でのバッチ挿入 MyBatis では、通常、バッチ挿入操作は動的 SQL を使用して実装されます。複数の挿入値を含む S を構築することによって

MyBatis ページングプラグインの原理の詳細な説明 MyBatis ページングプラグインの原理の詳細な説明 Feb 22, 2024 pm 03:42 PM

MyBatis は優れた永続層フレームワークであり、XML とアノテーションに基づいたデータベース操作をサポートし、シンプルで使いやすく、豊富なプラグイン メカニズムも提供します。その中でも、ページング プラグインは、よく使用されるプラグインの 1 つです。この記事では、MyBatis ページング プラグインの原理を詳しく説明し、具体的なコード例で説明します。 1. ページング プラグインの原理 MyBatis 自体はネイティブ ページング機能を提供しませんが、プラグインを使用してページング クエリを実装できます。ページング プラグインの原理は主に MyBatis を傍受することです

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

Linuxのchageコマンドの機能と動作原理の詳細な分析 Linuxのchageコマンドの機能と動作原理の詳細な分析 Feb 24, 2024 pm 03:48 PM

Linuxシステムのchageコマンドは、ユーザーアカウントのパスワード有効期限を変更するコマンドであり、アカウントの最長使用日と最短使用可能日を変更することもできます。このコマンドはユーザー アカウントのセキュリティ管理において非常に重要な役割を果たし、ユーザー パスワードの使用期間を効果的に制御し、システムのセキュリティを強化します。 CHAGE コマンドの使用方法: CHAGE コマンドの基本構文は次のとおりです: chage [オプション] ユーザー名 たとえば、ユーザー「testuser」のパスワードの有効期限を変更するには、次のコマンドを使用できます。

Linux RPM ツールの機能と原理についての詳細な説明 Linux RPM ツールの機能と原理についての詳細な説明 Feb 23, 2024 pm 03:00 PM

Linux システムの RPM (RedHatPackageManager) ツールは、システム ソフトウェア パッケージのインストール、アップグレード、アンインストール、管理を行うための強力なツールです。これは RedHatLinux システムで一般的に使用されるソフトウェア パッケージ管理ツールであり、他の多くの Linux ディストリビューションでも使用されます。 RPM ツールの役割は非常に重要で、システム管理者とユーザーがシステム上のソフトウェア パッケージを簡単に管理できるようになります。 RPM を通じて、ユーザーは新しいソフトウェア パッケージを簡単にインストールし、既存のソフトウェアをアップグレードできます。

Astar ステーキングの原則、収入の解体、エアドロップ プロジェクトと戦略、および運営のナニー レベルの戦略 Astar ステーキングの原則、収入の解体、エアドロップ プロジェクトと戦略、および運営のナニー レベルの戦略 Jun 25, 2024 pm 07:09 PM

目次 Astar Dapp ステーキングの原則 ステーキング収益 潜在的なエアドロップ プロジェクトの解体: AlgemNeurolancheHealthreeAstar Degens DAOVeryLongSwap ステーキング戦略と運用 「AstarDapp ステーキング」は今年初めに V3 バージョンにアップグレードされ、ステーキング収益に多くの調整が加えられましたルール。現在、最初のステーキング サイクルが終了し、2 番目のステーキング サイクルの「投票」サブサイクルが始まったばかりです。 「追加報酬」特典を獲得するには、この重要な段階を把握する必要があります (6 月 26 日まで続く予定で、残りは 5 日未満です)。 Astarステーキング収入を詳しく説明します。

See all articles