目次
2. 速记方法定义
3. 调用父类方法
4. 计算属性名称
5. 展望未来:rest 和属性展开
6. 结论
ホームページ ウェブフロントエンド jsチュートリアル JavaScript オブジェクト リテラルが優れていると言えるのはなぜでしょうか?

JavaScript オブジェクト リテラルが優れていると言えるのはなぜでしょうか?

Feb 22, 2017 pm 01:43 PM

ECMAScript 2015 より前は、JavaScript のオブジェクト リテラル (オブジェクト初期化子とも呼ばれます) の機能は非常に弱かったです。定義できるプロパティは 2 つだけです:

  • 共通のキーと値のペア { name1: value }

  • Getters { get name(){..} } と setters { set name(val){.. } }、計算する値を設定および取得するために使用されます。

残念なことに、オブジェクト リテラルのすべての使用法は、たった 1 つの簡単な例でカバーできます:

JS Bin で試す

var myObject = {  
  myString: 'value 1',
  get myNumber() { return this.myNumber;
  },
  set myNumber(value) { this.myNumber = Number(value);
  }
};
myObject.myString; // => 'value 1'  myObject.myNumber = '15';  
myObject.myNumber; // => 15
ログイン後にコピー

JavaScript はプロトタイプ ベースの言語であるため、すべてがオブジェクトです。この言語は、オブジェクトの作成、構造化、プロトタイプへのアクセスに関して、単純な構造を提供する必要があります。

オブジェクトの定義とそのプロトタイプの設定は一般的なタスクです。私は常に、プロトタイプの設定は単一の構文を使用してオブジェクト リテラルによって直接サポートされるべきだと感じています。

残念ながら、リテラルの制限により、直接的な解決策はありません。オブジェクト リテラルを結合し、プロトタイプを設定するには、Object.create() を使用する必要があります。

JS Bin で試してください

var myProto = {  
  propertyExists: function(name) { return name in this;    
  }
}; var myNumbers = Object.create(myProto);  
myNumbers['array'] = [1, 6, 7];  
myNumbers.propertyExists('array'); // => true  myNumbers.propertyExists('collection'); // => false
ログイン後にコピー

私の意見では、これは不快な解決策です。 JavaScript はプロトタイプに基づいていますが、プロトタイプからオブジェクトを作成するのはなぜそれほど面倒なのでしょうか?

幸いなことに、JavaScript は変わりつつあります。イライラする問題の多くは、JavaScript で段階的に解決されています。この記事では、ES2015が上記の問題をどのように解決し、追加の利点のためにオブジェクトリテラルを改善するかを説明します。 name

    それまでの間、最新の提案 (ステージ 2)、つまりオブジェクトの残りのプロパティとプロパティ拡張演算子について学んでいきましょう。
  • 1. オブジェクトの構築中にプロトタイプを設定します

    すでにご存知のとおり、既存のオブジェクトのプロトタイプにアクセスする方法の 1 つは、ゲッター属性 __proto__ を使用することです。 .__proto__ myObject のプロトタイプ オブジェクトを返します。
  • 良いニュースは、ES2015 では、オブジェクト リテラル { __proto__: protoObject } のプロトタイプを設定するための属性名としてリテラル __proto__ を使用できることです。

    让我们用 __proto__ 重写一下上面那个例子,让它看起来好一点:

    Try in JS Bin

    var myProto = {  
      propertyExists: function(name) { return name in this;    
      }
    }; var myNumbers = {  
      __proto__: myProto,
      array: [1, 6, 7]
    };
    myNumbers.propertyExists('array'); // => true  myNumbers.propertyExists('collection'); // => false
    ログイン後にコピー

    myNumbers 对象使用原型 myProto 创建,这可以通过特殊属性 __proto__ 实现。

    这个对象通过简单的语句创建,而不需要额外的函数例如 Object.create()。

    如你所见,使用 __proto__ 是简单的。我偏爱简单直接的解决方案。

    有点说跑题了,回到主题来。我认为获得简单和可靠的解决方案需要通过大量的设计和实践。如果一个解决方案是简单的,你可能认为它同样也很容易被设计出来,然而事实并不是这样:

    • 让它变得简单明了的过程是复杂的

    • 让它变得复杂和难以理解却很容易

    如果某个东西看起来太复杂或者用起来不舒服,很可能它的设计者考虑不周。

    元芳,你怎么看?(欢迎在文章底部发表评论参与讨论)

    2.1 使用 __proto__ 的特例

    尽管 __proto__ 看似简单,却有一些特殊的场景你需要格外注意。

    为什么我要说 JavaScript 对象字面量很酷?

    在对象字面量中 __proto__ 只允许使用一次。多次使用的话 JavaScript 会抛出异常:

    Try in JS Bin

    var object = {  
      __proto__: {
        toString: function() { return '[object Numbers]' }
      },
      numbers: [1, 5, 89],
      __proto__: {
        toString: function() { return '[object ArrayOfNumbers]' }
      }
    };
    ログイン後にコピー

    上面例子中的对象字面量使用了 __proto__ 属性两次,这是不允许的。这种情况下,会抛出一个错误 SyntaxError: Duplicate __proto__ fields are not allowed in object literals。

    JavaScript 限制了只允许使用 object 或者 null 作为 __proto__ 属性的值。使用其它原生类型(如字符串、数值、布尔类型)或者 undefined 会被忽略,并不能改变对象的原型。

    看一个例子:

    Try in JS Bin

    var objUndefined = {  
      __proto__: undefined }; Object.getPrototypeOf(objUndefined); // => {}  var objNumber = {  
      __proto__: 15 }; Object.getPrototypeOf(objNumber); // => {}
    ログイン後にコピー

    上面的例子里,对象字面量使用 undefined 和数值 15 来设置 __proto__ 值。因为只有对象或者 null 才允许被使用,objUndefined 和 objNumber 仍然是它们默认的原型:简单 JavaScript 对象 {}。__proto__ 的赋值被忽略了。

    当然,尝试使用原生类型来设置对象的原型,这本身是很奇怪的。所以在这里做限制是符合预期的。

    2. 速记方法定义

    现在对象字面量中可以使用一个更短的语法来声明方法,省略 function 关键字和冒号。这被叫做速记方法定义(shorthand method definition)。

    让我们用新的方式来定义一些方法:

    Try in JS Bin

    var collection = {  
      items: [],
      add(item) { this.items.push(item);
      },
      get(index) { return this.items[index];
      }
    };
    collection.add(15);  
    collection.add(3);  
    collection.get(0); // => 15
    ログイン後にコピー

    add() 和 get() 是 collection 中使用快捷的方式定义的方法。

    一个很好的地方是这样声明的方法是具名的,这对于调试有帮助。执行 collection.add.name 将返回函数名称 'add'。

    3. 调用父类方法

    一个有趣的改进是能够使用 super 关键字来访问从原型链继承下来的属性。看下面的例子:

    Try in JS Bin

    var calc = {  
      sumArray (items) { return items.reduce(function(a, b) { return a + b;
        });
      }
    }; var numbers = {  
      __proto__: calc,
      numbers: [4, 6, 7],
      sumElements() { return super.sumArray(this.numbers);
      }
    };
    numbers.sumElements(); // => 17
    ログイン後にコピー

    calc 是 numbers 对象的属性。在 numbers 的方法 sumElements 里面,要调用原型 calc上的方法,可以使用 super 关键字: super.sumArray()。

    所以 super 是从原型链访问被继承的属性的一个快捷的方法。

    在上一个例子里,我们也可以直接调用 cale.sumArray(),不过 super 是一个更好的选择因为它访问对象的原型链。它的存在清晰地暗示了继承的属性将被使用。

    3.1 使用 super 的限制

    在对象字面量中, super 只能用在速记方法定义中

    如果在普通的方法声明 { name: function() {} } 中使用它,JavaScript 会抛异常:

    Try in JS Bin

    var calc = {  
      sumArray (items) { return items.reduce(function(a, b) { return a + b;
        });
      }
    }; var numbers = {  
      __proto__: calc,
      numbers: [4, 6, 7],
      sumElements: function() { return super.sumArray(this.numbers);
      }
    }; // Throws SyntaxError: 'super' keyword unexpected here numbers.sumElements();
    ログイン後にコピー

    上面的代码里,方法 sumElements 被定义为:sumElements:function(){...}。由于 super要求在速记方法中使用,在其中调用 super 将抛出异常:SyntaxError: 'super' keyword unexpected here。

    这个限制不会对对象字面量声明有多少影响,因为大部分情况下我们没有理由不用速记方法定义,毕竟它语法更简单。

    4. 计算属性名称

    在 ES2015 之前,对象初始化器的属性名称是字面量,大多数情况下是静态字符串。要创建一个动态计算的属性名,你不得不使用属性访问器:

    Try in JS Bin

    function prefix(prefStr, name) { return prefStr + '_' + name;
    } var object = {};  
    object[prefix('number', 'pi')] = 3.14;  
    object[prefix('bool', 'false')] = false;  
    object; // => { number_pi: 3.14, bool_false: false }
    ログイン後にコピー

    当然,这种定义属性的方法差强人意。

    计算属性名称能更优雅地解决这个问题。

    当我们从表达式计算属性名称,将代码放在方括号之间 {[expression]: value}。这个表达式计算结果将成为属性名。

    我真的很喜欢这个语法:短而简单。

    让我们改进上面的代码:

    Try in JS Bin

    function prefix(prefStr, name) { return prefStr + '_' + name;
    } var object = {  
      [prefix('number', 'pi')]: 3.14,
      [prefix('bool', 'false')]: false };
    object; // => { number_pi: 3.14, bool_false: false }
    ログイン後にコピー

    [prefix('number', 'pi')] 通过计算 prefix('number', 'pi') 表达式来设置属性名称, 得到的结果是 'number_pi'。

    相应地, [prefix('bool', 'false')] 将第二个属性名称设为 'bool_false'。

    4.1 Symbol 作为属性名

    Symbols 也可以被用来计算属性名称,只需要将它包含在方括号中:{ [Symbol('name')]: 'Prop value' }。

    例如,使用特殊属性 Symbol.iterator 来迭代遍历一个对象的自有属性名,代码如下:

    Try in JS Bin

    var object = {  
       number1: 14,
       number2: 15,
       string1: 'hello',
       string2: 'world',
       [Symbol.iterator]: function *() { var own = Object.getOwnPropertyNames(this),
           prop; while(prop = own.pop()) { yield prop;
         }
       }
    }
    [...object]; // => ['number1', 'number2', 'string1', 'string2']
    ログイン後にコピー

    [Symbol.iterator]: function *() { } 定义一个属性来用于迭代遍历对象自有属性。展开操作符 [...object] 使用迭代器并返回自有属性列表。

    5. 展望未来:rest 和属性展开

    对象字面量的 Rest 和属性展开 是新的标准草案中的一个提案(stage 2),意味着这一特性是新版本 JavaScript 的规范的候选。

    数组的 展开和 rest 操作符 已经被实现了。

    Rest 属性 允许我们从解构赋值左侧使用对象来收集属性,看下面的例子:

    Try in JS Bin

    var object = {  
      propA: 1,
      propB: 2,
      propC: 3 }; let {propA, ...restObject} = object;  
    propA; // => 1  restObject; // => { propB: 2, propC: 3 }
    ログイン後にコピー

    属性展开 允许将源对象的自有属性拷进对象字面量内部。在上面的例子中,对象字面量从 souce对象中收集额外的属性。

    Try in JS Bin

    var source = {  
      propB: 2,
      propC: 3 }; var object = {  
      propA: 1,
      ...source
    }
    object; // => { propA: 1, propB: 2, propC: 3 }
    ログイン後にコピー

    6. 结论

    JavaScript 在快速进步。

    即使是相对小的结构比如对象字面量在 ES2015 中都有相当大的改进,更别说还有一大堆新特性在草案中。

    你可以从初始化器中使用 __proto__ 属性直接设置对象的原型,这比使用 Object.create() 要更方便。

    方法声明可以写成更简短的形式,这样你就不用写 function 关键字了。然后在速记方法中可以使用 super 关键字,它能提供方便的对被继承原型链上属性的访问。

    如果一个属性名在运行时计算,现在你可以使用计算属性名称 [表达式] 来初始化对象。

    的确,对象字面量现在很酷!

    你觉得呢?欢迎在下方发表评论参与讨论。

    以上就是为什么我要说 JavaScript 对象字面量很酷的内容,更多相关内容请关注PHP中文网(www.php.cn)!


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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)

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

MySQLクエリ結果の配列をオブジェクトに変換するにはどうすればよいですか? MySQLクエリ結果の配列をオブジェクトに変換するにはどうすればよいですか? Apr 29, 2024 pm 01:09 PM

MySQL クエリ結果の配列をオブジェクトに変換する方法は次のとおりです。 空のオブジェクト配列を作成します。結果の配列をループし、行ごとに新しいオブジェクトを作成します。 foreach ループを使用して、各行のキーと値のペアを新しいオブジェクトの対応するプロパティに割り当てます。新しいオブジェクトをオブジェクト配列に追加します。データベース接続を閉じます。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

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

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

PHP における配列とオブジェクトの違いは何ですか? PHP における配列とオブジェクトの違いは何ですか? Apr 29, 2024 pm 02:39 PM

PHP では、配列は順序付けられたシーケンスであり、要素はインデックスによってアクセスされます。オブジェクトは、new キーワードによって作成されたプロパティとメソッドを持つエンティティです。配列へのアクセスはインデックス経由で、オブジェクトへのアクセスはプロパティ/メソッド経由で行われます。配列値が渡され、オブジェクト参照が渡されます。

PHP の Request オブジェクトとは何ですか? PHP の Request オブジェクトとは何ですか? Feb 27, 2024 pm 09:06 PM

PHP の Request オブジェクトは、クライアントからサーバーに送信される HTTP リクエストを処理するために使用されるオブジェクトです。 Request オブジェクトを通じて、リクエストを処理して応答するために、リクエスト メソッド、リクエスト ヘッダー情報、リクエスト パラメータなどのクライアントのリクエスト情報を取得できます。 PHP では、$_REQUEST、$_GET、$_POST などのグローバル変数を使用して、要求された情報を取得できますが、これらの変数はオブジェクトではなく配列です。リクエスト情報をより柔軟かつ便利に処理するために、次のことができます。

C++ 関数がオブジェクトを返すときは何に注意する必要がありますか? C++ 関数がオブジェクトを返すときは何に注意する必要がありますか? Apr 19, 2024 pm 12:15 PM

C++ では、関数がオブジェクトを返すときに注意する点が 3 つあります。 オブジェクトのライフサイクルは、メモリ リークを防ぐために呼び出し元によって管理されます。ぶら下がりポインタを回避し、動的にメモリを割り当てるかオブジェクト自体を返すことにより、関数が戻った後もオブジェクトが有効なままであることを確認します。コンパイラーは、パフォーマンスを向上させるために、返されたオブジェクトのコピー生成を最適化する場合がありますが、オブジェクトが値セマンティクスによって渡される場合、コピー生成は必要ありません。

PHP 関数はどのようにオブジェクトを返すのでしょうか? PHP 関数はどのようにオブジェクトを返すのでしょうか? Apr 10, 2024 pm 03:18 PM

PHP 関数は、return ステートメントに続いてオブジェクト インスタンスを使用してオブジェクトを返すことにより、データをカスタム構造にカプセル化できます。構文: functionget_object():object{}。これにより、カスタム プロパティとメソッドを使用してオブジェクトを作成し、オブジェクトの形式でデータを処理できるようになります。

See all articles