>  기사  >  웹 프론트엔드  >  JavaScript 개체 속성의 특성과 DefineProperty 메서드에 대한 간략한 설명

JavaScript 개체 속성의 특성과 DefineProperty 메서드에 대한 간략한 설명

青灯夜游
青灯夜游앞으로
2019-11-30 16:51:032209검색

JavaScript 개체 속성의 특성과 DefineProperty 메서드에 대한 간략한 설명

객체는 순서가 지정되지 않은 속성의 모음이며 이러한 속성은 일부 특성 값(속성 속성으로 이해될 수 있음)으로 생성됩니다. 이러한 특성 값은 구현에 사용됩니다. JavaScript 엔진이므로 JavaScript에 직접 액세스할 수 없습니다.

JavaScript는 이러한 특성 값을 사용하여 속성의 동작(속성이 삭제, 열거, 수정 등인지 여부)을 정의합니다.

예를 들어 전역적으로 정의된 속성은 창에 마운트됩니다. 창에서 이 속성을 삭제하려는 경우에는 불가능합니다. 즉, 창의 속성을 구성할 수 없습니다. delete window.obj //false

Function.prototype 다른 값으로 수정해도 원래 값은 변하지 않습니다. 쓸 수 없습니다.

예를 들어 for in은 프로토타입 체인의 속성을 열거할 수 있지만 모든 프로토타입의 최상위는 Object.prototype이지만 for in은 이를 열거하지 않습니다. 따라서 Object.prototype은 열거 가능하지 않습니다.

속성은 두 가지 유형으로 나뉩니다: 1개의 데이터 속성, 2개의 접근자 속성. 예: 일반적으로 객체에 설정한 속성은 기본적으로 데이터 속성이고 Window의 속성은 접근자 속성입니다.

이 속성이 데이터 속성인지 접근자 속성인지 어떻게 알 수 있나요?

Object.getOwnPropertyDescriptor(속성이 위치한 객체, 속성) 메소드를 사용하세요. 객체를 반환합니다. accessor 속성이 사용되면 객체 속성에는 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: ?}

Data attribute

● 데이터 업스트림에는 읽고 쓸 수 있는 데이터 값의 위치가 포함되어 있습니다. 값에는 4개의 데이터 속성이 있습니다. 해당 동작을 설명하는 속성입니다. 이러한 값은 직접 액세스할 수 없고 내부 값이므로 사양에서는 이를 두 쌍의 대괄호로 묶습니다.

 ● 속성 구성 가능 여부: [[Configurable]]: 테이블에서 삭제를 통해 속성을 삭제할 수 있는지, 속성의 특성을 수정할 수 있는지, 접근자 속성으로 속성을 수정할 수 있는지 여부

 ● 속성이 열거 가능한지 여부 : [[Enumerable] ]: for-in 루프를 통해 테이블이 속성을 반환할 수 있습니까?

● 속성 수정 가능 여부: [[Writable]]

● 속성의 데이터 값: [[value]] 읽을 때 속성, 이 위치에서 읽고 쓰기 속성을 입력할 때 새 값을 이 위치에 저장하십시오.

일반적으로 정의된 속성으로, 처음 세 개의 기본값은 true이고 마지막 값은 정의되지 않습니다.

프로퍼티의 기본 특성을 수정하려면 Object.defineProperty(프로퍼티가 위치한 객체, 프로퍼티 이름, 디스크립터 객체) 메소드를 사용하세요.

Object.defineProperty 메소드의 두 번째 매개변수 속성의 이름이 존재하지 않는 경우, 이 메소드는 이 속성을 생성하며, value를 제외한 이 속성의 속성의 기본값은 모두 false입니다. 즉, Object.defineProperty 메소드를 사용하여 생성된 속성을 일반 속성처럼 열거, 구성 및 쓰기 가능하게 하려면 이 속성 값의 속성을 true로 변경해야 합니다. 그렇지 않으면 거짓입니다.

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,
        })

접속자 속성

접속자 속성에는 쓰기 가능 및 값이 포함되어 있지 않습니다. 여기에는 getter 및 setter 함수 쌍이 포함되어 있습니다. 접근자 속성을 읽을 때 getter 함수가 호출되고 유효한 값이 됩니다. 값, 접근자 속성에 쓸 때(속성 수정) setter 함수가 호출되고 새 값이 전달됩니다. 접근자는 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제