美文网首页JavaScript
JavaScript--Object相关内容

JavaScript--Object相关内容

作者: 蒜泥捣莓 | 来源:发表于2022-08-25 21:55 被阅读0次

    一、实例方法(原型方法)

    1、defineGetter

    可以将一个函数绑定在当前对象的指定属性上,当那个属性的值被读取时,你所绑定的函数就会被调用。

    2、defineSetter

    可以将一个函数绑定在当前对象的指定属性上,当那个属性被赋值时,你所绑定的函数就会被调用。

    3、lookupSetter

    导出对应的set方法。

    4、lookupGetter

    导出对应get方法。

    class Person{
        constructor(){
            this.age = 18
        }
    }
    //调用对应的__defineGetter
    let person = new Person()
    //定义get 访问对应的属性的时候调用的方法 属性名   handler
    person.__defineGetter__('age',function(){
        console.log('getter调用了');
        return '18'
    })
    console.log(person.age);
    //定义对应的set 用于设置的时候
    person.__defineSetter__('username',function(value){
        console.log('setter调用了 传入的值'+value);
        // this.username = value 循环调用问题 递归死循环
    })
    person.username = 'jack'
    console.log(person);
    //获取对应的get方法 指定的属性
    let get = person.__lookupGetter__('age')
    let set = person.__lookupSetter__('username')
    console.log(get);
    console.log(set);
    
    5、hasOwnProperty *

    会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)

    所有继承了 [Object] 的对象都会继承到 hasOwnProperty 方法。这个方法可以用来检测一个对象是否含有特定的自身属性;和 [in]运算符不同,该方法会忽略掉那些从原型链上继承到的属性。

    注意:即使属性的值是 nullundefined,只要属性存在,hasOwnProperty 依旧会返回 true

    class Person{
        constructor(){
            this.age = 18
        }
    }
    Person.prototype.username = 'jack'
    let person = new Person()
    person.sex = '女'
    //判断对象上是否具备属性 返回布尔类型
    console.log(person.hasOwnProperty('age')); //true
    console.log(person.hasOwnProperty('sex')); //true
    console.log(person.hasOwnProperty('username')); //false
    
    6、isPrototypeOf *

    判断当前对象(构造函数的原型对象)是否处在对应参数对象的原型链上 返回布尔类型。

    class Son extends Person{
        constructor(){
            super()
        }
    }
    //判断当前对象(构造函数)是否处在对应参数对象的原型链上 返回布尔类型
    console.log(Object.prototype.isPrototypeOf(person)); //true
    let son = new Son()
    console.log(Person.prototype.isPrototypeOf(son)); //true
    
    7、propertyIsEnumerable

    此方法可以确定对象中指定的属性是否可以被 for...in循环枚举,但是通过原型链继承的属性除外。如果对象没有指定的属性,则此方法返回false`。

    // 返回boolean类型 属性是否是可以枚举(可以遍历 for-in遍历)
    let obj = {
        arr:[1,2,3],
        o:{key:1},
        v:123,
        f:()=>{},
        b:false
    }
    //判断当前属性是否可以枚举 可以遍历
    console.log(obj.propertyIsEnumerable('v')); //true
    console.log(obj.propertyIsEnumerable('arr')); //true
    console.log(obj.propertyIsEnumerable('o')); //true
    console.log(obj.propertyIsEnumerable('f')); //true
    console.log(obj.propertyIsEnumerable('b')); //true
    
    8、valueOf

    返回指定对象的原始值。

    // valueOf提取对应的值
    console.log(new Object().valueOf());
    
    9、toString和toLocaleString

    toString() 方法返回一个表示该对象的字符串。

    toLocaleString() 方法返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的(locale-specific purposes)而重载使用。

    // toString 转为字符串类型 引用类型出现的结果[object Object]
    console.log(new Object().toString());
    //toLocalString 转为本地格式的字符串 千位分隔
    console.log(Number(123456789).toLocaleString());
    

    二、实例属性

    1、__proto__ 隐式原型
    let obj = new Object()
    console.log(obj.__proto__) 
    
    2、constructor

    返回 [Object] 的构造函数(用于创建实例对象)。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。

    let obj = new Object()
    console.log(obj.constructor) //指向对应的构造函数
    

    三、静态方法

    1、assign*

    assign 将后面的对象拷贝到第一个对象里面 返回的是一个新的对象 这个对象和原本第一个对象的地址一致(实现浅拷贝)

    let target = {}
    let obj =  Object.assign(target,{name:'jack'},{age:18})
    console.log(obj);
    console.log(target);
    

    注意:只会拷贝源对象 可枚举的自身的 属性到目标对象

    2、create*

    用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。

    //create 创建一个对象
    let obj1 = {name:"张三"}
    let obj2 = Object.create(obj1)
    console.log(obj2); //将对应obj1加到对应的obj2的原型上
    console.log(obj2 == obj1);
    class Person{
        constructor(){
            this.name = 'tom'
        }
    }
    let person = Object.create(Person) //根据传入的对象的类型来创建对应的对象
    console.log(person); //函数 Class本质就是构造函数
    
    3、keys、values和entries*
    • keys方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。
    • values方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用[for...in]循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
    • entries方法方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 [for...in]循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。
    //keys values entries 返回的都是一个迭代器
    let obj = {
        name:'jack',
        age:18,
        sex:'男'
    }
    //获取所有的key
    let objKeys = Object.keys(obj) //返回所有key组成的伪数组
    //获取所有的value
    let objValues = Object.values(obj) //返回所有key组成的伪数组
    //获取所有的键值对
    let objEntries = Object.entries(obj) //返回所有key组成的伪数组
    console.log(objKeys);
    console.log(objValues);
    console.log(objEntries);
    //这三个获取到的数组都可以进行遍历
    objEntries.forEach(arr=>{
        console.log(`key:${arr[0]} value : ${arr[1]}`);
    })
    
    4、is*

    判断两个值是否为[同一个值],如果满足以下任意条件则两个值相等:

    • 都是 [undefined]
    • 都是 [null]
    • 都是 true 或都是 false
    • 都是相同长度、相同字符、按相同顺序排列的字符串
    • 都是相同对象(意味着都是同一个对象的值引用)
    • 都是数字且
      • 都是 +0
      • 都是 -0
      • 都是 [NaN]
      • 都是同一个值,非零且都不是 NaN
    Object.is(25, 25);                // true
    Object.is('foo', 'foo');          // true
    Object.is('foo', 'bar');          // false
    Object.is(null, null);            // true
    Object.is(undefined, undefined);  // true
    Object.is(window, window);        // true
    Object.is([], []);                // false
    var foo = { a: 1 };
    var bar = { a: 1 };
    Object.is(foo, foo);              // true
    Object.is(foo, bar);              // false
    
    5、freeze和isFrozen*
    • Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
    • Object.isFrozen()方法判断一个对象是否被[冻结]。
    // 一个对象默认是可扩展的,所以它也是非冻结的。
    Object.isFrozen({}); // === false
    
    // 一个不可扩展的空对象同时也是一个冻结对象。
    var vacuouslyFrozen = Object.preventExtensions({});
    Object.isFrozen(vacuouslyFrozen) //=== true;
    
    // 一个非空对象默认也是非冻结的。
    var oneProp = { p: 42 };
    Object.isFrozen(oneProp) //=== false
    
    // 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
    // 因为 p 属性仍然是可以配置的 (而且可写的).
    Object.preventExtensions(oneProp);
    Object.isFrozen(oneProp) //=== false
    
    // 此时,如果删除了这个属性,则它会成为一个冻结对象。
    delete oneProp.p;
    Object.isFrozen(oneProp) //=== true
    
    // 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的。
    var nonWritable = { e: "plep" };
    Object.preventExtensions(nonWritable);
    Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
    Object.isFrozen(nonWritable) //=== false
    
    // 把这个属性改为不可配置,会让这个对象成为冻结对象。
    Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
    Object.isFrozen(nonWritable) //=== true
    
    // 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的。
    var nonConfigurable = { release: "the kraken!" };
    Object.preventExtensions(nonConfigurable);
    Object.defineProperty(nonConfigurable, "release", { configurable: false });
    Object.isFrozen(nonConfigurable) //=== false
    
    // 把这个属性改为不可写,会让这个对象成为冻结对象。
    Object.defineProperty(nonConfigurable, "release", { writable: false });
    Object.isFrozen(nonConfigurable) //=== true
    
    // 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的。
    var accessor = { get food() { return "yum"; } };
    Object.preventExtensions(accessor);
    Object.isFrozen(accessor) //=== false
    
    // ...但把这个属性改为不可配置,会让这个对象成为冻结对象。
    Object.defineProperty(accessor, "food", { configurable: false });
    Object.isFrozen(accessor) //=== true
    
    // 使用 Object.freeze 是冻结一个对象最方便的方法。
    var frozen = { 1: 81 };
    Object.isFrozen(frozen) //=== false
    Object.freeze(frozen);
    Object.isFrozen(frozen) //=== true
    
    // 一个冻结对象也是一个密封对象。
    Object.isSealed(frozen) //=== true
    
    // 当然,更是一个不可扩展的对象。
    Object.isExtensible(frozen) //=== false
    
    6、seal和isSealed*
    • Object.seal()方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
    • Object.isSealed() 方法判断一个对象是否被密封。
    // 新建的对象默认不是密封的。
    var empty = {};
    Object.isSealed(empty); // === false
    
    // 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象。
    Object.preventExtensions(empty);
    Object.isSealed(empty); // === true
    
    // 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的。
    var hasProp = { fee: "fie foe fum" };
    Object.preventExtensions(hasProp);
    Object.isSealed(hasProp); // === false
    
    // 如果把这个属性变的不可配置,则这个属性也就成了密封对象。
    Object.defineProperty(hasProp, 'fee', {
      configurable: false
    });
    Object.isSealed(hasProp); // === true
    
    // 最简单的方法来生成一个密封对象,当然是使用 Object.seal.
    var sealed = {};
    Object.seal(sealed);
    Object.isSealed(sealed); // === true
    
    // 一个密封对象同时也是不可扩展的。
    Object.isExtensible(sealed); // === false
    
    // 一个密封对象也可以是一个冻结对象,但不是必须的。
    Object.isFrozen(sealed); // === true ,所有的属性都是不可写的
    var s2 = Object.seal({ p: 3 });
    Object.isFrozen(s2); // === false, 属性"p"可写
    
    var s3 = Object.seal({ get p() { return 0; } });
    Object.isFrozen(s3); // === true ,访问器属性不考虑可写不可写,只考虑是否可配置
    
    7、preventExtensions和isExtensible*
    • Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
    • Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
    // 新对象默认是可扩展的。
    var empty = {};
    Object.isExtensible(empty); // === true
    
    // ...可以变的不可扩展。
    Object.preventExtensions(empty);
    Object.isExtensible(empty); // === false
    
    // 密封对象是不可扩展的。
    var sealed = Object.seal({});
    Object.isExtensible(sealed); // === false
    
    // 冻结对象也是不可扩展。
    var frozen = Object.freeze({});
    Object.isExtensible(frozen); // === false
    
    8、getPrototype和setPrototypeOf*
    • Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
    • Object.setPrototypeOf() 方法设置一个指定的对象的原型 ( 即,内部 [[Prototype]] 属性)到另一个对象或 [null]。
    let obj = {}
    Object.setPrototypeOf(obj,{
        username:'jack',
        age:18
    })
    console.log(obj.username);//obj的这个原型上进行设置
    console.log(obj.age);//obj的这个原型上进行设置
    let obj1 = new Object()
    console.log(obj1.username); //undefined
    //getPrototypeOf 获取指向的原型对象
    let pro = Object.getPrototypeOf(obj)
    let obj1Pro = Object.getPrototypeOf(obj1)
    console.log(pro); //{username:'jack',age:18}
    console.log(pro == Object.prototype);//false
    console.log(obj1Pro == Object.prototype);//Object.prototype true
    
    9、getOwnPropertyDescriptor 和getOwnPropertyDescriptors *
    • Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
    • Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。
    let obj = {
        name:'jack'
    }
    //getOwnPropertyDescriptorc 获取属性的详情信息 返回一个属性对象(es的内置对象)
    let property =  Object.getOwnPropertyDescriptor(obj,'name')
    console.log(property);
    
    //获取所有的属性详情信息 返回也是一个对象 这个对象里面包含对应的key 值为对应的属性对象
    let objs =  Object.getOwnPropertyDescriptors(obj)
    console.log(objs);
    
    10、getOwnPropertyNames和getOwnProperSymbols
    • Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。
    • Object.getOwnPropertySymbols() 方法返回一个给定对象自身的所有 Symbol 属性的数组。
    //获取所有的属性名 组成一个数组或者是伪数组
    console.log(Object.getOwnPropertyNames(obj));
    let sy = Symbol()
    obj[sy] = 'hello'//属性名为symbol的属性
    //获取所有属性名为symbol值的属性
    console.log(Object.getOwnPropertySymbols(obj));
    
    11、defineProperty***

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

    let obj = {}
    //给对象添加属性
    // defineProperty 定义一个属性 参数是对象  属性名  属性对象
    //  (属性对象 value 对应的值 writeable 是否可以修改 enumerable 是否可以遍历 configurable 删除可以删除)
    Object.defineProperty(obj,'name',{
        value:'jack',
        writable:true, //可以修改
        enumerable:true, //可以遍历 for in
        configurable:true //可以删除
    })
    console.log(obj); //多一个name属性
    obj.name = 'hello' //跟writable属性相关为false就不能修改
    delete obj.name //跟configurable相关 为false 不能删除
    console.log(obj); 
    for(let key in obj){
        console.log(key); //enumerable为false 就不能进行遍历
    }
    

    属性对象的基础属性

    • value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined
    • writable:当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。 默认为 false
    • enumerable:当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false
    • configurable:当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false

    属性对象的访问器属性

    注意:已经存在的情况才可以调用

    • get:属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 **默认为 [undefined]。

    • set:属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 [undefined]

    • enumerable

    • configurable

    //以访问器属性来写(后面的俩个内容可以不写默认为false)
    Object.defineProperty(obj,'age',{
        set(value){ //设置值的时候调用 value等于后面传递的值
            console.log('set执行了');
            mockObj.age = value
        },
        get(){ //获取值的时候
            console.log('get执行了');
            return mockObj.age
        },
        // enumerable:true, //可以遍历 for in
        // configurable:true //可以删除
    })
    console.log(obj.age); //调用了get的返回值
    obj.age = 20 //调用了set方法
    console.log(obj.age); //调用了get的返回值
    delete obj.age
    console.log(obj.age);
    console.log(obj);
    

    扩展:vue2是由对应的Object.defineProperty和观察者模式实现

    12、Object.defineProperties

    Object.defineProperties 本质上定义了 obj 对象上 props 的可枚举属性相对应的所有属性。

    // defineProperties  定义多个属性 对象  属性对象
    let object = {
    
    }
    Object.defineProperties(object,{
        name:{
            writable:true,
            value:"张三",
            enumerable:true,
            configurable:true
        },
        sex:{
            // writable:true,
            // value:"男",
            enumerable:true,
            configurable:true,
            get(){
                return '男'
            },
            set(value){
                console.log('设置方法调用了')
            }
        }
    })
    console.log(object);
    

    四、vue2双向数据绑定实现

    1、v-model来实现双向数据绑定
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    
    <body>
      <div id="app">
            <input type="text" v-model="message">
            {{message}}
      </div>
      <script src="./lib/vue.js"></script>
      <script>
        new Vue({
          el: "#app",
          data: {
            message:"你好啊"
          }
        })
      </script>
    </body>
    
    </html>
    
    2、底层实现(模拟实现)
    <!DOCTYPE html>
    <html lang="en">
    
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
        </head>
    
        <body>
            <div id="app">
                <input type="text" v-model="message">
                {{message}}
                <input type="text" v-model="title">
                {{title}}
            </div>
        </body>
        <script>
            class Vue {
                constructor(option) {
                    this.option = option
                    //通过对应的el属性传入的选择器选择对应的元素
                    this.el = document.querySelector(option['el'])
                    //提取data
                    this.data = option['data']
                    //虚拟对象
                    this.mockData = {}
                    //获取初始的模板
                    this.template = this.el.innerHTML
                    this.rander() //初次渲染
                    this.wacth() //调用监听
                }
                rander() {
                    let that = this
                    //读取{{}}包起来的内容 替换
                    //{{}}
                    this.el.innerHTML = this.template.replace(/\{\{[\w.]+\}\}/g, function (v) { //表示匹配的内容
                        // v {{message}} ==> 你好啊
                        let key = v.substr(2, v.length - 4)
                        return that.data[key] //调用get
                    })
                    //读取对应的input的v-model属性
                    //找所有的input框 在input在所有有对应的v-model属性 将他里面的value值变了
                    Array.from(this.el.querySelectorAll('input'))
                    //得到所有代理v-model属性的input框
                        .filter((input) => input.attributes['v-model'])
                    //接着遍历
                        .forEach(vmInput => {
                        //给对应的value进行赋值
                        vmInput.value = that.data[vmInput.getAttribute('v-model')] //调用get
                        //给对应的input框添加事件 oninput事件
                        vmInput.oninput = function () {//观察者
                            that.data[vmInput.getAttribute('v-model')] = this.value //调set
                            vmInput.focus() //获取焦点
                        }
                    })
                }
                //监听
                wacth() {
                    let _this = this
                    Object.keys(this.data).forEach(key => {
                        _this.mockData[key] = _this.data[key] //初始赋值操作
                        Object.defineProperty(_this.data, key, {
                            get() {
                                return _this.mockData[key]
                            },
                            set(value) {
                                _this.mockData[key] = value
                                _this.rander()
                            }
                        })
                    })
                }
    
            }
            new Vue({
                el: "#app",
                data: {
                    message: "你好啊",
                    title:'你好'
                }
            })
        </script>
    
    </html>
    

    相关文章

      网友评论

        本文标题:JavaScript--Object相关内容

        本文链接:https://www.haomeiwen.com/subject/ghbzgrtx.html