vue2のデータプロキシを理解するためのObject.defineProperty()メソッドの詳細説明

休日最初の記事 基礎知識の点に関しては、まだまだ自分が弱いと感じています。
休みを利用してもう一度見直してみましょう

Object.defineProperty() については、このメソッドの多くはインタビュー中に残ります。インタビュアーが vue2 と vue3 の違いを尋ねると、このメソッドに触れずにはいられません。vue2 の最下層は Object.defineProperty( )、vue3 はプロキシ オブジェクトです

ちなみに、両者の違いを列挙してみましょう。

1. パフォーマンスの最適化: Vue 3 では、応答性の高いシステムの書き直しが導入され、より効率的になります。Vue 3 は Proxy オブジェクトを使用します。Vue 2 の Object.defineProperty と比較して、Proxy は応答性の高いデータへの変更をより適切にキャプチャして追跡できるため、パフォーマンスが向上します。

2. サイズの縮小: Vue 3 はモジュール型開発手法を採用しており、オンデマンドで機能モジュールをインポートできるため、フレームワーク全体のサイズが縮小されます。

3. 合成 API: Vue 3 では、開発者が論理結合 API を通じて再利用可能な論理ブロックを作成できるようにする、コードを編成する新しい方法である合成 API が導入されています。Vue 2 の Options API と比較して、Composition API はより柔軟で構成可能であるため、コードの保守と再利用が容易になります。

4. TypeScript サポートの向上: Vue 3 は TypeScript に対してよりフレンドリーで、ts-check ディレクティブと関連する型宣言を通じて、より優れた型チェックとコード インテリジェント プロンプトを提供できます。

5. Teleport コンポーネント: Teleport コンポーネントは Vue 3 で導入され、DOM 内の他の場所にコンポーネントを簡単にレンダリングできます。これは、モーダル ボックス、ポップアップ レイヤーなどを扱うときに非常に便利です。

6. 再帰コンポーネントの改善: Vue 3 では、再帰コンポーネントのサポートが改善され、再帰コンポーネントの更新とレンダリングをより適切に処理できるようになりました。

Object.defineProperty() メソッドについて、もう少し詳しく見てみましょう。

Object.defineProperty は、オブジェクトの新しいプロパティを定義したり、既存のプロパティの特性を変更したりするために使用される JavaScript の組み込みメソッドです。

構文は次のとおりです。

Object.defineProperty(obj, prop, descriptor)

パラメータのメモ:

obj:要在其上定义属性的对象。
prop:要定义或修改的属性的名称。
descriptor:要定义或修改的属性的描述符对象,包含属性的各种特性。

記述子オブジェクト (構成アイテムとも呼ばれます) には、次のオプションのプロパティが含まれています。

value:属性的值,默认为 undefined。
writable:属性的值是否可以被修改。默认为 false,即该属性是只读的。
enumerable:属性是否可枚举(是否出现在对象的枚举属性中)。默认为 false。
configurable:属性是否可以被删除或修改特性。默认为 false。
get:读取时内部调用的函数
set:写入时内部调用的函数

"name" という名前のプロパティは、Object.defineProperty メソッドによって obj オブジェクトに定義されます。このプロパティの初期値は "John" で、書き込み、列挙、構成が可能です。後続の属性への代入操作により、属性の値が変更される可能性があります
。例:

const obj = {
    
    };

// 定义一个名为 "name" 的可写属性
Object.defineProperty(obj, 'name', {
    
    
  value: 'John',
  writable: true,
  enumerable: true,
  configurable: true
});

console.log(obj.name); // 输出 "John"

obj.name = 'Tom';
console.log(obj.name); // 输出 "Tom"

set (変更)、get (取得) を直接使用します。

const obj = {
    
    
  _name: 'John',
  get name() {
    
    
    return this._name;
  },
  set name(value) {
    
    
    this._name = value;
  }
};

console.log(obj.name); // 输出 "John"

obj.name = 'Tom';
console.log(obj.name); // 输出 "Tom"

まだ少しわかりにくいと感じていませんか? わかりやすい言葉で言いましょう:

すでにオブジェクトがある場合

let person = {
    
    
name:'莲花',
gender:'男',
}

次に、値 38 の属性 age を追加する必要があります。

オブジェクトに直接追加できます

let person = {
    
    
name:'莲花',
gender:'男',
age:38
}


実際の作業シナリオで、追加するプロパティが不明であり、特定の条件に従って動的に追加される場合、直接追加することは明らかに適切ではありません。直接追加することと、Object.defineProperty() を使用して追加することには、やはり違いがあります。直接追加できます。自由に変更でき、自由に削除でき、自由に列挙できます。Object.defineProperty() が追加するものは、変更を許可するか、削除を許可するかを制御できます、および列挙が許可されているかどうか。

例:

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,

})
//参数1:要添加参数的对象,给person对象添加,所以是person
//参数2,要添加的属性名,age
//参数3,配置项

直接追加する場合と Object.defineProperty() を使用して追加する場合の違いを印刷して確認します。
ここに画像の説明を挿入します
直接追加します。すべてのプロパティ名の色は同じです。ただし、Object.defineProperty() で作成すると、age プロパティ名の色がより明るくなります。他の 2 つのプロパティ名。これは、Object.defineProperty() 構成項目の列挙可能なプロパティがデフォルトで false であるため、つまり、デフォルトでは列挙できず、トラバーサルに参加しません。
console.log(Object.keys(person)) を実行して、person オブジェクトのすべてのプロパティ名で構成される配列を出力すると、直接追加されたプロパティ名は出力できるのに対し、Object.defineProperty() によって作成されたプロパティ名は出力できることがわかります。年齢がありません。

ここに画像の説明を挿入します
列挙したい場合は、enumerable を true に設定します

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,
enumerable:true,//控制属性是否可以被枚举,默认为false
})

age の値を変更したい場合は、直接追加して person.value を使用して変更できます。ただし、Object.defineProperty() によって作成された値は直接変更できません。これには書き込み可能な属性が関係します。デフォルトは false です。これは、デフォルトでは許可されていないことを意味します。変更して true に設定します。

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,
enumerable:true,//控制属性是否可以被枚举,默认为false
writable:true,//控制属性是否可以被修改,默认为false
})

age 属性が不要で削除したい場合は、person.age を削除することで直接追加できます。ただし、Object.defineProperty() によって作成された属性は直接変更できません。これには、デフォルトの設定可能な属性が必要です。つまり、デフォルトでは削除が許可されていないため、true に設定してください。

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,
enumerable:true,//控制属性是否可以被枚举,默认为false
writable:true,//控制属性是否可以被修改,默认为false
configurable:true,//控制属性是否可以被删除,默认为false
})

現在数値フィールドがある場合、要件は、年齢の値が数値の値を読み取る必要があること、つまり動的割り当てであることです。

直接追加します:

let number = 18
let person = {
    
    
name:'莲花',
gender:'男',
age:number
}

このように書くと確かに数値の値は年齢に割り当てられていますが、数値の値が後で変更されて、たとえば 20 になった場合でも、年齢の値はそれに応じて変更されず、元の 18 のままになります。

なぜなら、ステートメントが上から下に実行されると、最初の定義が完了します。将来、数値の値を変更することは、その数値自身の仕事だけです。最初の定義が完了したら終了し、人物オブジェクトの値は変更されません。また変わる、変わる。
手動で変更して年齢を再割り当てすると、実際に年齢の値が変更されます。ただし、数値が変更されるとすぐに年齢の値を変更したい場合は、Object.defineProperty() メソッドを使用する必要があります。 // 直接変更する手動で age を再割り当てします
。割り当ての例:


let number = 18
let person = {
    
    
name:'莲花',
gender:'男',
age:number
}
number = 20
person.age = number

//Object.defineProperty() 例:


Object.defineProperty(person,'age',{
    
    
//当读取person的age属性时,get(getter)函数就会被调用,且返回值是age的值
//get:function(){
    
    }
//return number
//})
//简写:
get(){
    
    
return number
}
//当修改person的age属性时,set(setter)函数就会被调用,且会收到修改的具体值
//打印value,当值改变的时候确实value接收到了,但是age并没有改变,这是因为person的age属性接收的是number的值
//set确实调用了,但是number变量的值没有改变,所以set中给number赋值
set(value){
    
    
number = value
}

このとき、numberの値が変化するとgetがトリガーされ、ageが直接numberの値を取得します。

person.ageを直接変更するとsetがトリガーされ、まずnumberの値が変更されてからgetがトリガーされ、Ageはnumberの値を取得します。

Object.defineProperty を理解したら、データ プロキシについて理解しましょう。

データ プロキシ:
1 つのオブジェクトを使用して、別のオブジェクトの属性の操作を代理したり、属性の変更を監視したり、属性の読み取りと書き込みを傍受したりできます。

例:

let obj = {
    
    
a:'1'
}

let obj2 = {
    
    
b:'2'
}
//obj2想访问obj.a,且可以修改obj.a的值
//给obj2新增属性a
//get中返回obj.a,即obj2新增的属性a拿的是obj.a的值
//set中修改,当obj2.a值发生改变的时候,再赋值给obj.a,再触发get,obj2.a再去拿obj.a的值
Object.defineProperty(obj2,'a',{
    
    
get(){
    
    
return obj.a
}
set(value){
    
    
obj.a= value
}

第一章終わり~~~

おすすめ

転載: blog.csdn.net/weixin_49668076/article/details/133420814