面向对象—JS对象的讲解

一、Object.create方法

  • Object.create是ES5新增的一个静态方法,用来定义一个实例对象。
  • 该方法可以指定对象的原型和对象特征,使用现有的对象来提供新创建的对象的proto。具体用法如下
    Object.create(prototype, descriptors)
    • prototype:必须参数,指定原型对象,可以为null
    • descriptors:可选参数,包含一个或多个属性描述符的 JS对象。属性描述符包括数据特性和访问器特性,其中数据特性说明如下
      • value:指定属性值
      • writable:默认为 false,设置属性值是否可写
      • enumerable:默认为false,设置属性是否可枚举(for/in)
      • configurable:默认为false,设置是否可修改属性特性和删除属性
    var obj1 = {name: "对象obj1"} // 字面量创建的对象,其原型指向 object
    console.log(obj1);
    console.log("obj1的原型:",obj1.__proto__);

    var obj2 = Object.create(null, { // 创建一个没有原型对象的对象
        name: {
            value: "对象obj2",
            writable: false
        }
    })
    console.log(obj2);
    console.log("obj2的原型:",obj2.__proto__); //undefind

    var obj3 = Object.create(obj1) // 创建一个原型指向obj1的对象
    console.log(obj3);
    console.log(obj3.name); // "对象obj1"。 obj3原型指向obj1,所以继承了obj1的属性。

二、对象的 constructor属性(即对象的构造函数)

    function MyArry() { } // 创建一个数组构造函数

    var arr1 = new MyArry() // 这里的 MyArry 肯定没有 数组相关的属性方法。如,push函数
    // arr2.push(1,2,3)  // 这里 MyArry的实例没有push方法
    console.log(arr1);

    MyArry.prototype = Array.prototype;
    var arr2 = new MyArry()
    arr2.push(1,2,3) // 这里arr2对象,就拥有 Array实例的属性方法了.如,push
    console.log(arr2);  // MyArry(3) [1,2,3]

    console.log(arr2.constructor); // Array() ,对象的构造函数引用出现问题,按理应该是指向MyArry。因为arr2是通过new MyArry创建的。
    // 解决对象构造函数,引用问题
    MyArry.prototype.constructor = MyArry
    console.log(arr2.constructor);

总结:

  • 一旦我们修改构造函数的原型对象,为防止引用出现问题,同时也要修改原型对象的constructor属性
  • constructor属性表示原型对象和构造函数之间的关联关系(实例对象和构造函数之间是存在指向关系的)。
    这个属性只是表明 对象和构造函数之间的关联关系,本身并没用什么特别的用途。【至少目前没发现有什么用】

 对constructor的使用:

  对 constructor 的使用,只是因为修改构造函数的原型对象时,为防止出现引用问题。

    function Star(uname, age){
        this.uname = uname;
        this.age = age;
    }
    Star.prototype = { // 这里修改了 构造函数的原型对象,而不是给原型对象添加属性。下面必须重新将构造函数重新指向回去。
        construtor: Star, // 使用 construtor 属性,重新设置 对象的 构造函数。
        sing: function(){
            console.log("我会唱歌");
        },
        movie: function(){
            console.log("我会演电影");
        }
    }

    var ldh = new Star("刘德华", 18)
    console.log(ldh);

总结:construtor属性只是表示 对象和构造函数之间的关系。没有设置construtor属性,从使用上来说,里面的方法还是可以正常调用的。

三、Object.fn和 obj.fn 的区别

  JS的面向对象是基于原型实现的。默认创建的对象都是 Object 类型的实例,所以JS对象中都会有 Object.prototype 上的方法。如,obj.hasOwnProperty 方法。

  但是使用继承的方法是有缺陷的,就是当一个对象的原型链不再指向 构造函数的原型对象时,这个对象就没有 Object.prototype上属性方法。所以JS把这些方法,在Object的静态属性上实现了下。

var obj = Object.create(null)  //  创建一个 对象原型 为 null 的对象,即obj 对象的原型链不再有Object对象。所以obj不再有 Object.propoty上的属性方法
obj.hasOwnProperty('name')  // 这里就会报错,因为 obj 自身和原型链上都 没有 hasOwnProperty方法

// 我们可以使用 Object上的静态方法,达到相同的功能。
Object.hasOwn(obj,'name')   // 使用上肯定要传递一个操作对象进来的。

 


 

1、对象属性的可枚举性和所有权:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Enumerability_and_ownership_of_properties

  a、属性的所有权是通过判断该属性是否直接属于某个对象决定的,而不是通过原型链继承的。

  b、对象的属性不同于数组,属性是可以从原型上获取到的。所以遍历对象的属性,要分是不是自身的属性,是不是可枚举。

     不然很多乱七八糟的属性都出来了,遍历就变得不可控了。(这里不讲人为去设置不可不枚举的功能,我们遍历对象,一般都是遍历自身的属性)

  c、自定义的 普通object对象的属性都是可枚举属性

  d、有的操作会忽略enumerable为false的属性。https://www.cnblogs.com/JiAyInNnNn/p/11457323.html

  目前,有四个操作会忽略enumerable为false的属性。
for…in循环:只遍历对象自身的和继承的可枚举的属性。
Object.keys():返回对象自身的所有可枚举的属性的键名。
JSON.stringify():只串行化对象自身的可枚举的属性。
Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。

2、对象属性的遍历:https://www.cnblogs.com/chenyablog/p/6477866.html

  a、Object.keys():返回一个数组,包括对象 自身的 (不含继承的)所有可枚举属性(不含Symbol属性)。然后使用数组的方法去遍历。【个人喜欢用这种】

  b、使用 for..in..遍历:循环遍历对象 自身的 和 继承的 可枚举属性(不含Symbol属性)。

  c、使用Object.getOwnPropertyNames(obj)遍历: 返回一个数组,包含对象 自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。

  d、使用Reflect.ownKeys(obj)遍历:返回一个数组,包含对象 自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举。

总结:普通的object对象属性的遍历,4种方法都可以。因为普通对象的属性都是可枚举的,也不会使用Symbol属性名,且没有继承的属性。如下创建的对象,

var obj = {'0':'a','1':'b','2':'c'};

3、js对象 属性的分类:https://juejin.cn/post/7033922034555944973 

  js对象属性分两种,数据属性(也是我们常用的)和 访问器属性

 

posted @ 2018-04-26 15:07  吴飞ff  阅读(125)  评论(0编辑  收藏  举报