美文网首页
Object对象的方法

Object对象的方法

作者: 竹杠敲头 | 来源:发表于2020-08-07 14:06 被阅读0次

    prototype是构造函数的属性,所以直接只用P.prototype.func1 = function(){},相当于给类设置原型。
    Object.setPrototypeOf()是给对象设置原型,是为了让obj.proto = Obj这种写法更加优雅,兼容性更高。属于es6推荐的写法


    Object.getPrototypeOf()

    返回参数对象的原型,这是或者原型最标准的方式。下面会介绍到

    const Person = function(){}
    const p = new Person():
    console.log(Object.getPrototypeOf(p) === Person.prototype) // true
    

    如上,Person是一个构造函数,p是Person的一个实例,p的原型就是Person的原型对象


    下面是几个特殊情况

    // 一个空对象的原型是Object.prototype
    Object.getPrototypeOf({}) === Object.prototype //true
    // Object.prototype的原型是null
    Object.getPrototypeOf(Object.prototype) === null //true
    //函数的原型是Function.prototype
    function func(){}
    Object.getPrototypeOf(func) === Function.prototype //true
    

    以上牵扯到原型和原型链的问题,可以查看我关于原型原型链的简单介绍


    Object.setPrototypeOf()

    Object.setPrototypeOf()能够为方法参数设置原型。接收两个参数,第一个参数为现有对象,第二个参数为原型对象。如下

    const p = {
      name:'ccg'
    };
    const p1 = {};
    Object.setPrototypeOf(p1,p);
    console.log(Object.getPrototypeOf(p1) === p) // true
    p1.name // ccg
    

    如上,p和p1是两个独立的对象,通过Object.setPrototypeOf(),将p1的原型设置为p,则可以通过Object.getPrototypeOf()方法进行验证。

    重点:被设置原型的对象会继承原型的所有属性


    使用new来模仿Object.setPrototypeOf()

    function Person(){};
    const p = new Person();
    //等同于
    const p = Object.setPrototypeOf({},Person.prototype);
    Person.call(p);
    

    如上,new Person是我们常用的写法。用Object.setPrototypeOf()的写法更好理解,相当于我们创建一个空对象,通过Object.setPrototypeOf()将空对象的原型设置为Person的原型对象,然后通过call方法将Person的构造函数(this)设置为p。


    Object.create()

    Object.create()是一个生成实例对象的常用方法。该方法接收一个参数,并且以参数为原型返回一个实例对象。
    该实例对象完全继承原型对象的属性和方法。
    参数为必填,否则会报错
    参数必须为对象,否则也会报错

    const person = {
      hairColor:'red',
      run(){
        console.log('running')
      }
    }
    const person2 = Object.create(person);
    person2.hairColor //red
    person2.run() //running
    

    如上,person是一个很普通的对象,使用Object.create()方法创建了一个person2,那么person就是person2的原型对象,person2继承person的所有属性和方法。

    下面是三种创建对象的方式,然而是等价的

    const p = Object.create({});
    const p2 = Object.create(Object.prototype);
    const p3 = new Object();
    

    当我们需要创建一个不继承任何属性的对象时,也就是说没有valueof和tosString方法时,如下

    const p = Object.create(null);
    

    我们知道一般对象的方法都是挂在Object.prototype上的,而Object.prototype的原型是null,也就是通过null创建的对象时没有任何属性的。
    有关介绍可以去看关于原型原型链的介绍

    当然Object.create()也接收第二个参数。该参数是一个描述属性对象,该对象会添加到实例对象上

    const p = Object.create({},{
           name:{
            value: 'ccg',
            enumerable: true,
            configurable: true,
            writable: true,
           },
           age:{
            value: 20,
            enumerable: true,
            configurable: true,
            writable: true,
           }
       })
    console.log(p.name)//ccg
    console.log(p.age)//20
    

    如上,我们通过一个空对象{}外加一个对象描述属性创建了一个实例p。

    通过Object.create创建的实例对象,也会继承原型对象的构造函数

    const Person(){}
    const p = new Person();
    const p2 = Object.create(p);
    p2.constructor === Person //true
    p2 instanceof Person //true
    

    Object.prototype.isPrototypeOf()

    实例对象的isPrototypeOf()方法,用来判断是否为参数对象的原型

    const person = {};
    const p = Object.create(person);
    const p2 = Object.create(p);
    person.isProtorypeOf(p);//true
    p.isProtorypeOf(p2);//true
    

    如上,p和person都是p2的原型,可以通过isPrototypeOf()来判断

    Object.prototype.isPrototypeOf({})//true
    Object.prototype.isPrototypeOf([])//true
    Object.prototype.isPrototypeOf(Object.create(null)) // false
    

    如上,是几种特殊方式


    Object.prototype.proto

    实例对象的proto (注意是两边各两个_)返回实例的原型对象。该属性可读可写。

    const p = {};
    const p2 = {};
    p2.__proto__ = p; 
    p.isPrototypeOf(p2) //true
    

    如上,p和p2都是两个独立的对象,通过proto将p2的原型对象设置为p。

    根据语言规定,proto是只有在浏览器才部署的,其他的环境不必部署。前后各两根下划线表名它本身是个内部属性,不应该暴露给使用者进行使用。
    所以我们进行原型修改时推荐使用Object.getPrototypeOf()和Object.setPrototypeOf()对原型对象进行读写和操作。

    在原型链中我们可以使用proto清晰的标识

    var A = {
      name: '张三'
    };
    var B = {
      name: '李四'
    };
    
    var proto = {
      print: function () {
        console.log(this.name);
      }
    };
    A.__proto__ = proto;
    B.__proto__ = proto;
    A.print() // 张三
    B.print() // 李四
    A.print === B.print // true
    A.print === proto.print // true
    B.print === proto.print // true
    

    如上,A和B和proto本身是相互独立的对象,我们通过proto将A和B的原型对象绑定再来proto对象上,所以A和B都可以共享proto的属性和方法。
    这便是我们JS的原型链继承

    获取原型对象方法的比较

    const obj = {};
    obj.__proto__ //Object.prototype
    obj.constructor.prototype //
    Object.getPrototypeOf(obj); //Object.prototype
    

    如上,是三种或者对象原型的方法。
    前两种相对来说不是很可靠。proto是部署在浏览器上,其他环境不会部署,obj.constructor.prototype 在手动修改原型对象时可能会失效

    const P = function(){}
    const p = new P();
    const C = function(){}
    C.prototype = p;
    const c = new C();
    c.constructor.prototype === p//false
    c.constructor.prototype = p
    

    如上C的原型对对象指向了p,但是C的实例c的原型对象缺没有指向p,还是需要重新设置c的构造函数的原型为p才可以

    因此推荐使用Object.setPrototypeOf()进行原型对象设置


    Object.prototype.hasOwnProperty()

    实例对象的hasOwnProperty()方法,用来判断是否含有参数属性(实例自己的参数,非原型或原型链的参数)
    hasOwnProperty()也是JS中唯一一个进行处理对象不行时,不会进行原型链属性遍历的方法

    const arr= [];
    arr.hasOwnProperty(length)//true
    arr.hasOwnProperty(toString)//false
    

    如上,arr是一个数组对象,可以用hasOwnProperty来判断length属性,但是无法判断toString属性,因为toString是原型链上的属性。

    in 和for...in...

    in运算符返回一个Boolean类型的值,用来判断对象是否有某个属性,但是不会区分原型属性还是原型链上的属性

    'length' in [];//true
    'toString' in [];//true
    

    如上,length是数组原有的属性,toString是数组的原型Objec上的属性,都被in判断为true

    const p = {name:'ccg'};
    const p2 = Object.create(p,{
        age:{
              value:20
        }
    })
    for(item in p2){
        console.log(item);
    }
    //ccg
    //20
    

    如上,通过p生成对象p2,age是p2的自身属性,name属性时继承于p。但是通过for...in...都可以变量出来
    当然我们可以在for...in...的循环内使用使用hasOwnProperty来判断是自身属性还是原型属性。

    完结,撒花

    相关文章

      网友评论

          本文标题:Object对象的方法

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