欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

javascript的对象问题及总结

程序员文章站 2022-04-06 10:57:41
一 js中的对象是什么? 是一个容器,封装了属性(property)和方法(method),由若干键值对(key-value)组成 是对实物的抽象,实物间关系转换成了对象间关系,模拟现实的情况,转换为针对对象的编程。 - 例如将动物抽象成一类对象,此类对象有着动物中特有的属性和动作,不同于植物,而动 ......

一  js中的对象是什么?

  • 是一个容器,封装了属性(property)和方法(method),由若干键值对(key-value)组成
  • 是对实物的抽象,实物间关系转换成了对象间关系,模拟现实的情况,转换为针对对象的编程。

- 例如将动物抽象成一类对象,此类对象有着动物中特有的属性和动作,不同于植物,而动物中又分有猪,狗,鸡不同类型的事物对象,这些类型事物对像既有着动物类型的属性和动作,又有着自身独特类型的属性和动作,可以这样一直细分下去,直到每一种动物的个例,也就是对象的实例了,它不仅具备上层事物共有的属性和方法,也有着自己独特个性,是一个独特的个体。

1-1 js的对象如何创建?

-- 对象可通过对象字面量({}),构造函数(如new Object(),或自定义),Object.create等方式创建。

1-1-1 对象字面量,与new Object()创建对象方式的异同?

相同点:创建的对象在使用上是一致的,var a = {}  // 是var a= new Object()的语法糖

不同点:初始化的过程有些区别,new Object()是通过构造函数实例化对象,{ }是直接创建JSON对象,且在初始化时可以直接赋值,相比{ }比较高效

1-1-2 访问及修改对象的属性

-- 对象是由键值对组成,对象的键名又称属性(property),都是字符串类型,键名符合标识名条件或是数字可省略" ",系统会默认自动转为对应的字符串,键值可以是任意类型,若键值是函数,则该属性又可被称为方法,像函数般调用。

  • 使用 . 或 [ ]  访问或修改增添对象的属性
  • delete删除属性
  • in检查是否属于自身的属性
  • Object.keys(obj)查看所有自身可枚举属性,Object.getOwnPropertyNames(obj)包括自身不可枚举的属性如数组中的"length",都返回属性名数组
  • for...in 循环遍历对象本身属性
  • Object.observe(obj,function(changes))观察对象属性变化

1-1-2eg1:对象字面量式创建

  <script>
    //对象字面量式创建
    var obj = {
      name: 'fermin',
      run: function () {
        alert('run');
      } 
    };
    obj.age = 18;          //添加属性
    console.log(obj.age);  //18
    delete obj.age;   
    //删除属性,注意:不能删除继承的属性,会返回false,删除不存在的属性不会报错,且返回true
    alert(obj.age);  // undefined,访问不存在的属性返回undefined
    alert("age" in obj);
    //false,  注意:in对对象拥有的属性都返回ture,无论是否是继承的,无法识别继承属性
    console.log(Object.keys(obj)); //["name","run"] //Object.keys()返回所有本身属性名
    for (let i in obj) {
      console.log(i); 
     //name run //for..in 遍历可enumerable的自身和继承的属性,可加obj.hasOwnProperty(i),过滤为自身属性
    }
    obj.run();      //run //用点号访问属性和方法
    obj['run']();   //run //用[]访问属性和方法
    alert("toString" in obj); //true 
</script>

构造函数:构造函数创建对象是借用Object.create(原型) 来实现。

1-1-2eg2:new Object() 创建  (访问和修改对象属性与上述相同)

<script>
    //new Object()创建
    var obj = new Object(); //new可以省略
    obj.name = 'fermin';
    obj.age = 18;           //添加属性
    obj.run = function () {
        alert('run');
    };                    //添加属性
    delete obj.age;   //删除属性  //delete只能删除对象的属性如:var a=1; delete a  //false
    alert(obj.age);  // undefined,访问不存在的属性返回undefined
    alert("age" in obj);//false
    console.log(Object.keys(obj)); //["name","run"] 
    for (let i in obj) {
      console.log(i);  //name run 
    }
    obj.run();      //用点号访问属性和方法
    obj['run']();   //用[]访问属性和方法 
    alert("toString" in obj);  //true
</script>

1-1-2eg3:自定义构造函数

<script>
    //自定义构造函数
    function Person(name) {
      this.name = name; 
    }
    var obj = new Person("fermin");
    obj.age = 18;
    obj.run = function () {
      alert("run");
    }; //添加属性
    alert(Object.keys(obj)); //name,age,run
    for (let i in obj) {
      console.log(i); //name age run
    }
    obj.run(); // run
    obj['run'](); // run
    alert("toString" in obj); //true
</script>

1-1-2eg4:Object.create(原型)   //  Object.create(Object.prototype) <==> new Object()

<script>
    //Object.create(原型);
    var obj = Object.create(null); 
    //原型为null,不能继承Object.prototype中的属性
    obj.name = 'fermin';
    obj.age = 18;           //添加属性
    obj.run = function () {
        alert('run');
    };                    //添加属性
    delete obj.age;   //删除属性
    alert(obj.age);  // undefined,访问不存在的属性返回undefined
    alert("age" in obj);//false
    console.log(Object.keys(obj)); //["name","run"] 
    for (let i in obj) {
      console.log(i);  //name run 
    }
    obj.run();      //用点号访问属性和方法
    obj['run']();   //用[]访问属性和方法 
    alert("toString" in obj);  //false //没有继承Object.prototype中的属性
</script>

1-1-3 new一个对象的过程

var obj = new Function();

  • 创建一个空对象     // var obj = {};
  • 将实例的__proto__属性指向构造函数的prototype原型 //  obj__proto__ = Function.prototype
  • 将构造函数的指针指向实例  // Function.call(obj)

1-1-3eg1:模拟new过程

<script>
function Person(name) { this.name = name; } var obj = Person("fermin"); //不用new obj = {}; obj.__proto__ = Person.prototype; Person.call(obj); obj.age = 18; obj.run = function () { alert("run"); }; //添加属性 alert(Object.keys(obj)); //name,age,run for (let i in obj) { console.log(i); //name age run } obj.run(); // run obj['run'](); // run alert("toString" in obj); //true </script>

1-1-4 函数中this的指向问题  (避免在函数中包含多层this,往往第一层代表调用的对象,第二层就表示window了)

-- this的指向在函数执行时才能确定,总是指向调用该函数的对象

  • 由new调用,指向新建的对象                                 //在构造函数执行
  • 由call,apply,bind调用,指向绑定的对象            //在强制绑定对象执行
  • 由上下文调用,指向所属的上下文对象                  //在对象属性执行
  • 没有所属对象时,严格模式指向undefined或指向全局对象(window或global)  //在普通函数执行

1-1-4-eg1:

<script>
    var obj1= {
      a:3,
      b:{
        a:10,
        fn:function(){
          console.log(this.a); //undefined
          console.log(this); //window
        }
      }
    };
    var j = obj1.b.fn;
    j();
    //将fn赋值给变量j时,obj调用fn没有执行,所以它最终指向的是window,而不是obj
    
    var obj2 = {
      a : 'A',
      fn: function () {
         console.log(this.a);
      }
    };
    obj2.fn();       //"A"          // this ===obj2
    obj2.fn.call({a: 'AA'}); //"AA" // this === {name: 'AA'}
    var fn1 = obj2.fn;
    fn1();           //undefined   //this === window
</script>

二  object对象的方法

2-1  六个实例对象方法,继承Object.prototype

  • valueOf():返回当前对象对应的值,默认返回对象本身  // var o1 = new Object (); o1.valueOf === o1   //true
  • toString():将对象转换为字符串形式并返回  // var o2 = {a : 1}; o2.toString()  // [object Object]    //用Object.prototype.toString.call()  更准确的判断类型[object,对象类型11种/ Number/ String/ Boolean/ Object/ Array/ Function/ Null/ Undefined/ RegExp/ NaN/ Infinite]
  • toLocalString():将对像转换为本地对应的字符串并返回
  • hasOwnPropoty():判断某个属性是否是自身的非继承属性,是的返回true
  • isPrototypeOf(): 判断当前对象是为另一对象原型,是返回true
  • propertylsEnumerable():判断某个属性是否可枚举

2-2  对象属性的特征 attributes 对象用Object.getOwnPropertyDescriptor(obj,字符串属性名)读取。

  • value:表示该属性的值,默认undefined
  • writable:表示该属性的值是否可改,默认true
  • enumerable:表示该属性名是否可枚举,默认true   //改为false时,for..in 及Object.keys()JSON.stringify()不遍历该属性,可成私密属性
  • configurable:表述该对像是否可配置,默认true     //var 声明的变量会为false,没声明为false,如a=1或this.a=1   //改为false时,writable可从true改为false,当writable为true可改value值,其他值不可修改,不能再用delete删除该属性
  • get:表属性取值函数(getter)默认undefined   //定义后,writable不能为true且定义value的值 // get,set为存取器的命令,常使用于某属性值需依赖对象内部数据场合。 //  利用存取器可以实现数据对象与DOM对象的双向绑定
  • set:表属性存值函数(setter)默认underfined  //定义后,writable不能为true且定义value的值

2-3 定义对象属性的attributes对象,下面两种方法定义后,属性中的writable,enumerable,configurable的值默认值又都会变为false

  • Object.defineProperty(obj,字符串属性名,attributesObj)
  • Object.defineProperties(obj,{字符串属性名: attributesObj,字符串属性名: attributesObj,...})

2-3-eg1:定义单一attribules属性

<script>
  var o = Object.defineProperty({}, "p", {
    value: 3,
    writable: false,
    enumerable: true,
    configurable: false
  });
  alert(o.p);  //3
  o.p = 33;
  alert(o.p);  //3  //writable为false,修改不了该属性的值 
</script>

2-3-eg2:定义多个attributes属性

<script>
  var o = Object.defineProperties({}, {
    p1: {
      value: 3,
      enumerable: true,
      writable: true, //configurable值没设定,默认为false
    },
    p2: {
      get: function () {
        return this.p1 + 6;
      },         //有get,就不能直接定义其value值
      enumerable: true,
      configurable: true
    }
  });
  alert(o.p1);  //3
  o.p1 = 4;     //writable,值为true后,可直接用.或[]修改该属性值,
  alert(o.p1);  //4
  alert(o.p2);  //10 
  Object.defineProperty(o, "p1",{value:33});
  //若再修改p1其它属性值会报错,因为一开始configurable为false
  alert(o.p1);  //33 
  //PS:当writable值为false,configurable值为true,只能在defineProperty()中修改
</script>

 2-4  对象的拷贝

--将一对象所有属性拷贝到另一个对象上,有重复的属性,将被覆盖

<script>
    var extend = function (to, from) {
      for (var property in from) {
        var descriptor = Object.getOwnPropertyDescriptor(from, property);
        if (descriptor && (!descriptor.writable 
          || !descriptor.enumerable
          || !descriptor.configurable
          || !descriptor.get
          || !desciptor.set)) {
          Object.defineProperty(to, property, descriptor); //都拷贝
        } else {
          to[property] = from[property];  
          //这个else遇存取器定义属性只拷贝值,适用于descriptor的5个特征都具备
        } 
      }
      return to; 
    };
    var aa = extend({a:1, b:2}, {a:11, bb:22});
    console.log(aa); //{a:11, b:2, bb:22}  
</script>

2-5  控制对象的状态

  • Object.preventExtensions(obj)   //无法再添加新属性,严格模式下添加会抛错,可用delete删除现有属性
  • Object.isExtensible(obj)   //没使用Object.preventExtensions(obj)返回false,使用了返回true
  • Object.seal(obj)  //无法添加新属性,也无法删除旧属性,现有属性的configurable会变为false
  • Object.isSeal(obj) //没使用Object.seal(obj)返回false,使用了返回true,且isExtensible返回false
  • Object.isFrozen(obj)  //是否被冻结,指不可扩展,所有属性不可配置,所有数据属性(即没有getter或setter组件的访问器的属性)都是不可写的。

2-5-eg:

<script>
    var o = new Object();
    Object.preventExtensions(o);
    o.p = 1;
    console.log(o.p); // undefined
    console.log(Object.isExtensible(o)); //false
</script>