zoukankan      html  css  js  c++  java
  • 对象的简单认识

    对象

    对象其实可以看做有许多键值对组合成的一个无序集合,可以通过键俩访问值。值一般由,基本数据类型 和 object 组合。

    对象的创建

    有三种方式:

    1. new构造函数

    1. 使用new来创建一个对象
      var person = new Object();
      甚至可以简写成为: var person = new Object;

    2. Object参数如果是一个对象,则直接返回对象本身

    var o = { a : 1};
    var p = new Object(o);
    alert(o === p); // true
    
    1. 传入原始数据类型,则返回包装对象
    var o1 = new Object("123");
    console.log(o1); // String{0:"1",1:"2",2:"3",length:3,__proto__: String, [[PrimitiveValue]]: "123"}
    
    var o2 = new Object(123);
    console.log(o2) // Number{123, __proto__: Number, [[PrimitiveValue]]: 123} 
    
    var o3 = new Object(true);
    console.log(o3)
    // Boolean {__proto__: Boolean, [[PrimitiveValue]]: true}
    
    // ------------ 下面是空对象 和不传参数一样。
    var o4 = new Object(null)
    console.log(o4) // Object{__proto__: Object}
    
    var o5 = new Object(undefined)
    console.log(o5) // Object{__proto__: Object}
    
    var o6 = new Object()
    console.log(o6) // Object{__proto__: Object}
    

    2. 对象字面量

    这是我们 最熟悉的一种,也是经常使用的一种,其实使用字面量只是隐藏了与使用new操作符相同的基本过程,于是也可以叫做语法糖。
    简单示例:

    var person = {
    	age : 24,
    	name: 'xiaoming',
    	1: true,  
    }
    

    注意,使用对象字面量方法来定义对象的时候,属性名会自动转化为字符串。
    就是上面示例,自动变成下面的。

    var person = {
    	'age' : 24,
    	'name': 'xiaoming',
    	'1': true,  
    }
    

    Object.create()

    ES5定义了一个名为Object.create()的方法,它创建一个新对象,第一个参数就是这个对象的原型,第二个可选参数用以对对象的属性进行进一步描述

    var o = Object({a:1})
    console.log(o) // Object{a:1,__proto__:object}
    

    注意:传入参数null来创建一个没有原型的新对象

    var o1 = Object.create(null); 
    
    var o2 = {};
    

    此时o1不会继承任何东西,甚至不包括基础方法。比如toString()和valueOf()。
    如果想要创建一个普通的空对象(例如,通过{}或new Object()创建的对象),需要传入Object.prototype, 这就是因为,这个函数的第一个参数就是原型对象。

    var o3 = Object.create(Object.prototype);
    var o4 = {};
    

    对象的引用

    如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。

    var o = {
    	a:1,
    }
    
    var p = o;
    console.log(p.a)  // 1
    
    p.a = 0;
    console.log(o.a) // 0
    

    对象的属性

    对象的属相操作,有两种 [] 和 点号(.)。
    点号(.), 在使用的时候,属性名必须符合标识符的命名规则。
    不存在的属性取值返回undefined。

    var o = {
    	a : 0,
    	1 : true,
    }
    
    o.b = 1;  // 可以增加属性,并赋值
    console.log(o.a) // 可以取值操作
    console.log(o.1) // 报错
    console.log(o.b)  // undefined  不存在的变量
    o.a = 2;  // 可以赋值操作
    console.log(o.a);
    

    [] 方括号中的值, 若是字符串,则直接访问。 如果非字符串类型且不符合标识符命名,则转成字符串访问,如果非字符串类型且符合标识符命名,则需要识别变量的值,变量未定义,则报错。
    在[] 访问属性的时候 是可以计算属性的

    var c = 1;
    var o = {}
    
    console.log(o[0]) // undefined   o[0] --> o['0'] 访问。
    console.log(o[a]) // 报错,a符合变量的命名规则,a未被定义,而报错
    
    console.log(o['a']) // undefined    o['a'] 访问。
    console.log(o[null]) // undefined , o[null] --> o['null']访问
    
    console.log(o[c + 1]) // undefined  o[c+1] --> o['4']访问
    

    注意 null和undefined不是对象,给它们设置属性会报错

    属性的删除

    使用delete运算符可以删除对象属性(包括数组元素)。
    delete是有返回值的,删除成功则返回true,删除不存在的属性或非左值时,返回false。当使用delete操作符删除不可配置的属性时,返回false,严格模式下会抛出TypeError错误
    将属性赋值为 null 和undefined 只是修改了属性的值。

    var o = {
    	a:1
    }
    console.log(delete o.a);//true
    console.log(o.a);//undefined
    console.log('a' in o);//false   in 操作符 可以判断对象是否具有该属性,但是无法判断是否是继承来的
    

    使用delete删除数组元素时,不会改变数组长度

    var a = [1,2,3];
    delete a[2];
    2 in a;//false
    a.length;//3
    

    属性的检测

    每一个javascript对象都和另一个对象相关联。“另一个对象”就是我们熟知的原型对象,每一个对象都会从原型对象继承属性。
    对象本身具有的属性叫自有属性,从原型对象继承而来的属性叫继承属性

    in: in操作符可以判断对象是否可以使用某一属性,但无法区别自有还是继承属性
    for-in: for-in循环可以遍历出该对象中所有可枚举属性
    hasOwnProperty(): 可以确定该属性是自有属性还是继承属性
    Object.keys(): 返回所有可枚举的自有属性
    Object.getOwnPropertyNames(): Object.keys()方法不同,Object.getOwnPropertyNames()方法返回所有自有属性(包括不可枚举的属性)

    属性描述符

    对象属性描述符分为, 数据属性 访问器属性

    数据属性

    数据属性(data property)包含一个数据值的位置,在这个位置可以读取和写入值。

    1. 可配置configuable

      • 可配置性决定是否可以使用delete删除属性,以及是否可以修改属性描述符的特性,默认值为true
      var o = {a:1};
      Object.defineProperty(o,'a',{
          configurable:false,
      });
      delete o.a; //false   严格模式下报错
      console.log(o.a);//1
      
      • 设置Configurable:false后,将无法再使用defineProperty()方法来修改属性描述符
      var o = {a:1};
      Object.defineProperty(o,'a',{
          configurable:false
      });
      // 报错不能修改属性
      Object.defineProperty(o,'a',{
          configurable:true
      });
      
      • writable的状态 只能是从true变为false
    2. 可枚举enumerable
      可枚举性决定属性是否出现在对象的属性枚举中,具体来说,for-in循环、Object.keys方法、JSON.stringify方法是否会取到该属性。

      var o = {a:1};
      Object.defineProperty(o,'a',{enumerable:false});
      for(var i in o){
          console.log(o[i]);//undefined
      }
      
    3. 可写性writable
      可写性决定是否可以修改属性的值,默认值为true

      var o = {a:1};
      Object.defineProperty(o,'a',{
          writable:false
      });
      console.log(o.a);//1
      o.a = 2;//由于设置writable为false,所以o.a=2这个语句会默认失效,严格模式会报错
      console.log(o.a);//1
      
    4. 属性值value
      属性值包含这个属性的数据值,读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值为undefined

    访问器属性

    访问器属性不包含数据值;它们包含一对儿getter和setter函数(不过,这两个函数都不是必需的)。在读取访问器属性时,会调用 getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。

    1. 可配置性Configurable
        表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为 true
    2. 可枚举性Enumerable
      可枚举性决定属性是否出现在对象的属性枚举中,比如是否可以通过for-in循环返回该属性,默认值为true
    3. getter 读
        在读取属性时调用的函数。默认值为undefined
    4. setter 写
        在写入属性时调用的函数。默认值为undefined
        和数据属性不同,访问器属性不具有可写性(Writable)。如果属性同时具有getter和setter方法,那么它是一个读/写属性。如果它只有getter方法,那么它是一个只读属性。如果它只有setter方法,那么它是一个只写属性。读取只写属性总是返回undefined

    get是一个隐藏函数,在获取属性值时调用。set也是一个隐藏函数,在设置属性值时调用,它们的默认值都是undefined。Object.definedProperty()中的get和set对应于对象字面量中get和set方法
    [注意]getter和setter取代了数据属性中的value和writable属性
    通常这里的get和set是用来 拦截数据访问和修改的。

    var o = {
    	get a(){
    		return 0;
    	}
    }
    
    console.log(o.a)  // 0
    o.a = 1 // 没有set方法, 默认失效
    console.log(o.a)  // 0
    // ---------------------------------------
    Object.defineProperty(o,'b',{
        get: function(){
            return 2;
        }
    })
    console.log(o.b);//2
    //由于没有设置set方法,所以o.a=3的赋值语句会静默失败
    o.b = 1;
    console.log(o.b);//2
    

    只有set

    var o = {}
    Object.defineProperty(o,'a',{
        set: function(){
            return 0;
        }
    })
    o.a = 1;
    console.log(o.a);//undefined
    

    通常情况下 get 和set是成对出现的, 并且你会发现,这样做,我们还需要空间来存储值。 这也是数据属性的不同之处吧。

    var o = {};
    Object.defineProperty(o,'a',{
        get: function(){
            return this._a;
        },
        set :function(val){
            this._a = val*2;
        }
    })
    o.a = 1;
    console.log(o.a);//2
    

    对象属性的获取和设置

    1. Object.getOwnPropertyDescriptor(对象,属性名)
      查看对象的属性,返回一个对象,包含了属性的特性。,当查看不存在的属性时,返回undefined。 并且只适用于自身的属性。
    var o = {a : 0};
    // Object {value: 0, writable: true, enumerable: true, configurable: true}
    console.log(Object.getOwnPropertyDescriptor(o,'a'));
    // undefined
    console.log(Object.getOwnPropertyDescriptor(o,'b')); 
    
    1. Object.defineProperty(对象,属性名, 属性描述)
      返回配置后的对象。
      使用该方法创建或配置对象属性的描述符时,如果不针对该属性进行描述符的配置,则该项描述符默认为false
    var o = {};
    Object.defineProperty(o,'a',{
    		value: 0,
    		writable: true,
    		enumerable: true,
    	});
    // /{value: 1, writable: true, enumerable: true, configurable: false}     没有配置由于没有配置configurable,所以它的值为false
    console.log(Object.getOwnPropertyDescriptor(o,'a'))
    
    1. Object.defineProperties(o, 属相描述)
      用于创建或配置对象的多个属性的描述符,返回配置后的对象。
    var o = {
    	a : 1,
    }
    
    Object.defineProperties(o,{
    	a:{enumerable:false},
    	b:{value:2}
    })
    
    //{value: 1, writable: true, enumerable: false, configurable: true}
    console.log(Object.getOwnPropertyDescriptor(o,'a'));
    //{value: 2, writable: false, enumerable: false, configurable: false}
    console.log(Object.getOwnPropertyDescriptor(o,'b'));
    
    1. Object.create(原型对象,描述)
      使用指定的原型和属性来创建一个对象。
    var o = Object.create(Object.property,{
    	a:{
    		value: 0,
    		writable: false,
    		enumerable: true,
    	},
    	b{
    		value: 1,
    	}
    })
    //{value: 0, writable: false, enumerable: true, configurable: true}
    console.log(Object.getOwnPropertyDescriptor(obj,'a'));
    // {value: 1, writable: true, enumerable: true, configurable: true}
    console.log(Object.getOwnPropertyDescriptor(obj,'b'))
    

    对象的拷贝

    浅拷贝

    使用for-in将对象的所有属性复制到新建的空对象中,并将器返回

    function simpleClone(o,cloneObj){
    	// 判断参数
        for(var i in obj){
            cloneObj[i] = obj[i];
        }
        return cloneObj;
    }
    

    使用属性描述符

    function simpleClone(o){
    	// 判断参数
    	var cloneObj = Object.create(Object.getPrototypeOf(o)); // 根据o对象的原型对象,创建新对象。
    	// 获取自身属性并迭代。 
    	Object.getOwnPropertyNames(o).forEach(function(propKey){
    		// 根据自身属性名 获取属相描述。
            var desc = Object.getOwnPropertyDescriptor(o,propKey);
            // 给克隆对象设置 属性描述
            Object.defineProperty(cloneObj,propKey,desc);
        });
        return cloneObj;
    }
    

    深拷贝

    复制对象的属性时,对其进行判断,如果是数组或对象,则再次调用拷贝函数;否则,直接复制对象属性

    function deepClone(o,cloneObj){
    	if(typeof o != 'object'){
            return false;
        }
        var cloneObj = cloneObj || {};  // 保证cloneObj不是null和undefined
    
        for(var i in o){
    		if(typeof o[i] === 'object'){ // 是对象继续递归拷贝
    			cloneObj[i] = (o[i] instanceof Array) ? [] : {};
                arguments.callee(o[i],cloneObj[i]);
    		}else{
    			cloneObj[i] = o[i];
    		}
        }
    
    }
    

    使用 json.
    先是对象转成字符串,然后在转成对象返回。

    function jsonDeepClone(o){
    	return JSON.parse(JSON.string(o))
    }
    
  • 相关阅读:
    Django 中间件
    Django之ORM介绍
    ORM相关操作
    Django Form表单
    Django REST framework 中文文档
    前端基础之BOM和DOM
    Django--ORM(2)
    Django--视图
    Django--路由系统
    Django--模板语言
  • 原文地址:https://www.cnblogs.com/cyrus-br/p/10490762.html
Copyright © 2011-2022 走看看