JavaScript语法之对象

Posted emptylee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript语法之对象相关的知识,希望对你有一定的参考价值。

今天总结一下关于对象的重点和容易理解不清的知识点。
 
1 javascript中主要有两种类型,即基本类型(包括string,number,boolean,null,undefined)和对象。而函数,数组,内置对象(String,Number,Boolean,Object,Function,Array,Date,RegExp,Error),这些都是对象的子类型(也可以叫复杂基本类型)。也就是说它们也是对象的一种类型,具备一些额外的行为,比如函数可以理解为可调用的对象。因为函数是对象的一种子类型,所以函数可以当作另一个函数的参数。
 
存储在对象容器内部的是这些属性的名称, 它们就像指针(从技术角度 来说就是引用) 一样, 指向这些值真正的存储位置。
例如:
var obj={
     func:function(){
         console.log(this); 
     }
};
从技术角度来说, 函数永远不会“属于” 一个对象。所以,对象里的方法,本质上是对象里的一个属性名指向一个函数。对象通过属性访问返回的函数和其他函数没有任何区别,除了this发生隐式绑定。
 
 
2 关于函数的拷贝 
 
浅拷贝,深拷贝:
由于对象的实例是存储在堆内存中然后通过一个引用值去操作对象,因此拷贝的时候就出现两种情况:拷贝引用和拷贝实例,这就是浅拷贝和深拷贝的区别。可以说,浅拷贝只拷贝一层实例,深拷贝是拷贝所有层的实例。
 
浅拷贝,是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。浅拷贝的外层源对象是拷贝实例,内层元素是拷贝引用。就是说,外面的整个对象肯定是复制一个新的实例,里面的元素,如果是基本类型的值,肯定也是复制值,如果是数组或者对象这样的对象类型,则是复制其引用。
常用方法:Array.prototype.slice(), Array.prototype.concat()  但是这两个函数都是用于数组。
若要浅拷贝对象,有var newObj = Object.assign( {}, myObject );,jQUery的extend,还可以:
 
var obj = { a:1, arr: [2,3] };
 
var shallowObj = shallowCopy(obj);
 
function shallowCopy(src) {
 
    var dst = {};
 
    for (var prop in src) {
 
        if (src.hasOwnProperty(prop)) {
           dst[prop] = src[prop];
       }
    }
 
     return dst;
 
}
 
 例子:
var a = [{c:1}, {d:2}];
var b = a.slice();
console.log(a === b); // 输出false,说明外层数组拷贝的是实例
a[0].c = 3;
console.log(b[0].c); // 输出 3,说明其元素拷贝的是引用
 
 
深拷贝:在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响
常用方法:JSON  var newObj = JSON.parse( JSON.stringify( someObj ) )。另外可以用递归函数。
 
综合的深拷贝函数:
var cloneObj = function(obj){
    var str, newobj = obj.constructor === Array ? [] : {};
    if(typeof obj !== ‘object‘){
        return;
    } else if(window.JSON){
        str = JSON.stringify(obj), //系列化对象
        newobj = JSON.parse(str); //还原
    } else {
        for(var i in obj){
            newobj[i] = typeof obj[i] === ‘object‘ ? 
            cloneObj(obj[i]) : obj[i]; 
        }
    }
    return newobj;
};
 
例子:
var a = {c: {d: 1}};
var b = $.extend(true, {}, a);
console.log(a === b); // 输出false
a.c.d = 3;
console.log(b.c.d); // 输出 1,没有改变。
 
 
3 属性与属性描述符
所有属性都有4种属性描述符(或叫数据描述符),分别是value(数据值),writable(可写的),enumerable(可枚举的),configurable(可配置的)。
若要查看某个属性的属性描述符,可以用:
Object.getOwnPropertyDescriptor( myObject, "属性名" );
若要修改某个属性的属性描述符,可以:
var myObject = {};
Object.defineProperty( myObject, "a", {
     value: 2,
     writable: true,
     configurable: true,
     enumerable: true
} );
myObject.a; // 2
 
writable,设置为false后表示不可写,则无法改变该属性的值。
enumerable,设置为false后,该属性无法出现在对象的属性枚举中,如for...in循环中遍历不到这个属性。
configurable,设置为false后,该属性变为不可配置,所以再想改回来是不可以的,即configurable改为false是单向操作。同时,设置为false后,用delete删除这个属性无效。
 
 
4 属性的getter和setter
getter和setter是隐藏函数,分别会在获取属性值和设置属性值时调用。因此,可以用getter和setter来改写单个属性的默认操作。
可以有两种格式去修改属性的默认操作:
var myObject = {
     // 给 a 定义一个 getter
     get a() {
          return 2;
     }
};
或:
Object.defineProperty(
     myObject, // 目标对象
     "b", // 属性名
     { // 描述符
          get: function(){ return this.a * 2 },
          // 确保 b 会出现在对象的属性列表中
          enumerable: true
     }
);
 
一般要给一个属性设置属性值时,getter和setter是成对出现的:
var myObject = {
     // 给 a 定义一个 getter
     get a() {
          return this._a_;
     },
     // 给 a 定义一个 setter
     set a(val) {
          this._a_ = val * 2;
     }
};
myObject.a = 2;
myObject.a; //4
 
 
欢迎互相交流,互相学习。前端开发QQ群:711357426
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

以上是关于JavaScript语法之对象的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript学习笔记(10)——JavaScript语法之操作DOM

javascript之面向对象学习笔记02

前端之JavaScript面向对象开发

前端之JavaScript面向对象开发

Json之语法,格式

JavaScript基础语法