ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript オブジェクトのプロパティと defineProperty メソッドの特性に関する簡単な説明

JavaScript オブジェクトのプロパティと defineProperty メソッドの特性に関する簡単な説明

青灯夜游
青灯夜游転載
2019-11-30 16:51:032231ブラウズ

JavaScript オブジェクトのプロパティと defineProperty メソッドの特性に関する簡単な説明

オブジェクトは順序付けされていない属性のコレクションであり、これらの属性はいくつかの特性値 (属性の属性として理解でき、それらとともに生まれます) を使用して作成されます。これは実装のために JavaScript エンジンによって使用されるため、JavaScript から直接アクセスすることはできません。

JavaScript は、これらの特性値を使用して属性の動作 (属性が削除されるか、列挙されるか、変更されるかなど) を定義します。

たとえば、グローバルに定義されたプロパティはウィンドウにマウントされます。ウィンドウ上でこの属性を削除したい場合は削除できません。つまり、ウィンドウ上のプロパティは構成できません。 delete window.obj //false

Function.prototype 別の値に変更しても、元の値は変わりません。書き込み可能ではありません。

たとえば、for in はプロトタイプ チェーン上のプロパティを列挙できますが、すべてのプロトタイプの先頭は Object.prototype ですが、for in はそれを列挙しません。したがって、Object.prototype は列挙可能ではありません。

属性は 2 つのタイプに分類されます: 1 データ属性 2 アクセサー属性。例: 一般に、オブジェクトに設定するプロパティはデフォルトではデータ プロパティですが、Window のプロパティはアクセサー プロパティです。

このプロパティがデータ プロパティであるかアクセサー プロパティであるかを確認するにはどうすればよいですか?

Object.getOwnPropertyDescriptor (プロパティが配置されているオブジェクト、プロパティ) メソッドを使用します。オブジェクトを返します。アクセサ属性が使用される場合、オブジェクト属性には enumerable、configurable、get、set が含まれます。このとき、オブジェクトが返すデータ属性には、value、writable、enumerable、configurable が含まれます。

var obj  = {name:'zwq',age:18};
console.log(Object.getOwnPropertyDescriptor(obj,'name'));  //name属性属性
//{value: "zwq", writable: true, enumerable: true, configurable: true}

console.log(Object.getOwnPropertyDescriptor(window,'name'));  //window上的name属性时访问器属性
//enumerable: true, configurable: true, get: ?, set: ?}

データ属性

●上位データの行にはデータ値が含まれています 位置は値の読み取りと書き込みが可能です データ属性には、その動作を説明する 4 つの属性があります これらの値は直接アクセスできず内部値であるため、仕様では 2 組のかっこで囲みます。

# 属性が構成可能かどうか: [[構成可能]]: テーブルが削除によって属性を削除できるかどうか、属性の特性を変更できるかどうか、および属性をアクセサー属性として変更できるかどうか

# 属性が列挙可能かどうか: [[Enumerable]]: テーブルは for-in ループを通じて属性を返すことができますか?

#● 属性が変更可能かどうか: [[Writable]]

● 属性のデータ値: [ [値]] 属性を読み取る場合はこの場所から読み取り、属性を書き込む場合はこの場所に新しい値を保存します。

一般的に定義された属性。最初の 3 つのデフォルト値はすべて true で、最後の値は未定義です。

プロパティのデフォルトの特性を変更する場合は、Object.defineProperty (プロパティが配置されているオブジェクト、プロパティの名前、記述子オブジェクト) メソッドを使用します。

Object.defineProperty メソッドの第 2 パラメーターのプロパティの名前が存在しない場合、このメソッドはこのプロパティを作成します。このプロパティのプロパティのデフォルト値は value を除いてすべて false です。つまり、Object.defineProperty メソッドで作成されたプロパティを通常のプロパティと同様に列挙可能、構成可能、および書き込み可能にしたい場合は、このプロパティ値のプロパティを true に変更する必要があります。それ以外の場合は false です。

var obj  = {name:'zwq',age:18};

        Object.defineProperty(obj,'name',{ 修改name属性的特性,值为haha,并且name属性不能修改值
            value:'haha',
            writable:false  //默认值是true,改为false,不可写。
        })

        Object.defineProperty(obj,'sex',{创建一个sex属性,这个属性不可枚举
            value:'woman',
            writable:true,
            configurable:true,
        })

アクセサー プロパティ

アクセサー プロパティには書き込み可能プロパティと値は含まれません。ゲッター関数とセッター関数のペアが含まれます。アクセサー プロパティを読み取る場合は、ゲッター関数が呼び出され、有効な値が返されます。アクセサー プロパティを書き込む場合 (プロパティを変更する場合)、セッター関数が呼び出され、新しい値が渡されます。アクセサには 4 つの特性が含まれます。

# 属性が構成可能かどうか: [[Configurable]]: テーブルが削除によって属性を削除できるかどうか、属性の特性を変更できるか、および属性をアクセサ属性

# 属性が列挙可能かどうか: [[Enumerable]]: テーブルが for-in ループを通じて属性を返すことができるかどうか

● [[Get]]: 呼び出される関数属性を読み取るとき。デフォルト値は未定義です。

##●[[Set]]: 属性を書き込む (または変更する) ときに呼び出される関数。デフォルト値は未定義です。

アクセサ プロパティを定義するには、Object.defineProperty() も使用する必要があります。

function Person(){
            this._name = 'zwq',
            this.age =  18
        }
        var person = new Person();
        
        
        Object.defineProperty(person,'name',{
            set(newValue){
                console.log('set');
                this._name = newValue   //设置或修改属性时,会调用set函数,把设置的值通过参数传进去后,用一个变量或属性保存。并且当调用get,return就是返回的这个值
            },
            get(){
                return this._name;   //当读取属性时 返回return的值
            }
            
        })

getter と setter の両方を指定する必要はありません。getter のみを指定すると、プロパティを書き込むことができなくなります。

vue の双方向データ ハイジャック バインディング (主にフォームで使用される) の原理は、Object.defineProperty を使用してデータ変更を検出することです。

双方向ハイジャック バインディングが発生すると、ビュー (ページの要素) が変更されると、それに応じてデータも変更されます。データが変更されると、ビューも変更されます。たとえば、以下の入力ボックスの内容が変更されると、データ (オブジェクトまたは配列) が変更されます。データの変更を検出します。以下の p テキストは、データの変更に応じて変更されます。

#上で紹介したように、データが変更されると set メソッドがトリガーされます。これから、データの変化を検出できます。

//检测对象的变化。
     var input = document.getElementById('Oinput');
        var view = document.getElementById('view');

        var data = {
            valueObj :{
                value:'zwq'
            }
        }
        //当输入框数据发生改变时,数据跟着改变
        input.oninput = function(){
            data.valueObj.value = this.value;
        }
        
        // 更新视图
        function upData(){   
            view.innerText = data.valueObj.value;
        }
        
        upData(data);
        obServe(data);

        // 监控某个对象是否发生改变
        function obServe(data){
           //判断当前传的是否是对象,如果不是,直接return
            if(!data || !(data instanceof Object)){return data}
       //获取所有属性名。使用keys方法可以获取所有属性名(包括原型上的)并保存带数组中
            var arrProperty = Object.keys(data);
       //遍历数组,调用defindRective检测每一个属性值的改变 
            arrProperty.forEach(function(key){
          defindRective(data,key,data[key]); //传入3个参数,当前对象,当前属性,当前属性值
            })
        }

        function defindRective(obj,key,val){
           obServe(val);   //使用递归,当想上面的数组,对象套对象的形式,由于里面的对象是一个引用值,无法检测里面的数据变化,所以使用递归。
            Object.defineProperty(obj,key,{  //核心:使用Object,definPropert的set检测数据的改变。
                set(newValue){
                    console.log(5);
                    if(newValue == val) return val;
                    val = newValue;
                    upData();   //当数据变化,跟新视图
                },
                get(){
                    return  val;
                }
            })
        }
// 监测数组,将数组原型重写
// 当操作数组的arr push pop unshift slice...才会检测
        let {push} = Array.prototype;
        var arr = [1,2,3];
        function upData(){
            console.log('更新');
        }
        Object.defineProperty(Array.prototype,'push',{
            value:(function(){
                return (...arg) => {
                    upData();
                    push.apply(arr,arg);
                }
            })()
        })
 arr.push(8,9);
Object.defineProperty を使用して配列とオブジェクトの変更を検出するため、これらを個別に実装する必要があります。また、データを追加すると検出されなくなります。

そのため、これを実現するためにプロキシが ES6 に追加されました。

Proxy&reflect简介:植入代理的模式,以简洁易懂的方式控制对外部对象的访问,利用set,get方法控制属性的读写功能,还有其余的has,desProperty。。等方法。但proxy兼容性不好,使用时要注意。

proxy是一个构造函数,通过代理的方式将你想到代理的对象传给构造函数,并且需要传入参数对象对读和写进行控制。使用new方法实例化代理的对象,

此后,当修改,或添加属性都使用代理的对象。

let data = {
    value:'zwq',
}
// let data = [1,2];
let oProxyData = new Proxy(data,{
    set(target,key,value,receiver){  //传入4个参数 对象 属性 属性值 代理的对象
        // target[key] = value;
        Reflect.set(target,key,value); //等同于上一步
        upData();
  },
    get(target,key,receiver){
        // console.log(target,key);
        Reflect.get(target, key);
    },
    has(target,key){ //当使用in时触发当前函数。
        return key in target;   //in --检测对象能否访问该属性,能访问返回true,不能false,无论是在实例还是原型中。
    }
});

console.log('valu' in oProxyData);

function upData(){
    console.log("更新啦");
}

oProxyData.value = 20;

本文来自 js教程 栏目,欢迎学习!

以上がJavaScript オブジェクトのプロパティと defineProperty メソッドの特性に関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。