添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
直爽的黄花菜  ·  UTC & GWT ...·  3 月前    · 
一直单身的冰棍  ·  c# wpf ...·  1 年前    · 
精彩文章免费看

JS对象的引用与赋值

javascript的一切实例都是对象,只是对象之间稍有不同,分为原始类型和合成类型。原始类型对象指的是字符串(String)、数值(Number)、布尔值(Boolean),合成类型对象指的是数组(Array)、对象(Object)、函数(Function)。

既然对象分为这两类,他们之间的最大差别是复制克隆的差别。普通对象存储的是对象的实际数据,而引用对象存储的是对象的引用地址,而把对象的实际内容单独存放,因为引用对象通常比较庞大,这是数据开销和内存开销优化的手段。通常初学者很难理解这部分内容,就像对象的原型一样,也是同一个概念。对象的原型也是引用对象,把原型的方法和属性放在单独内存当中,而对象的原型链则指向这个内存地址。尽管这部分内容比较拗口复杂,那其中的原理都是一致的,目的也一致。

var myArrayRef = new Array(0,1,2); //创建数组对象
var mySeconArrayRef = myArrayRef; // 对象复制.
myArrayRef[0] = 100; // 修改元素值
alert(mySeconArrayRef[0]);
*  javascript语言中创建的对象myArrayRef值中其时保存的是对象的引用(也就是一个地址). 
*  也就是 我用 new Array生成的保存在内存中,而new Array把它所在的地方告诉了myArrayRef,
*  myArrayRef又把这地址告诉了mySeconArrayRef 
*  他们两个都指向的是new Array生成对象的地址而不是把对象保存在myArrayRef中,
*  所以通过其中的一个去修改值时其时是修改他们同指象的那对象.
  var myVa = 'ABC'; //把ABC的值 赋予了myVa
  var myVb = myVa; // myVa 赋值给 myVb
  myVa = 'DEF'; //修改myVa
  console.log(myVa ); //ABC
// 把值保存在了变量里, 而不是引用地址,所以他们两个是相对独立的整体.

如果真要复制对象互不影响,则要通过转换赋值或者遍历key:value来复制你对象中的方法和属性

jquery转换赋值

  var data = {a:1,b:2,c:3,d:[0,1,2,3]};
  var str = JSON.stringify(data);
  var data1 = $.parseJSON(str); //$为jQuery对象需要引入jQuery包
  data1["e"] = 4;
  data1["d"][0] = 11;
  console.log(data);
  console.log(data1);
输出结果:
{a: 1, b: 2, c: 3, d: [0,1,2,3]}
{a: 1, b: 2, c: 3, d: [11,1,2,3], e: 4}
相互没有影响

我们需要封装一个函数,来对对象进行拷贝,通过for in 循环获取基本类型,赋值每一个基本类型,才能真正意义上的复制一个对象

  var obj = { a:10 };
  function copyObj(obj){
      var newobj = {};
      for ( var key in obj) {
          newobj[key ] = obj[key ];
      return newobj;
  var obj2 = copyObj(obj);
  obj2.a = 20;
  alert(obj.a); //10 

浅拷贝存在隐患,如果obj中,a的值不是10,而是一个对象,这样就会导致在for in中,将a这个对象的引用赋值为新对象,导致存在对象引用的问题

  var obj = {a:{b:10}};
  function copyObj(obj){
      var newobj = {};
      for ( var key in obj) {
          newobj[key ] = obj[key ];
      return newobj;
  var obj2 = copyObj(obj);
  obj2.a.b = 20;
  alert(obj.a.b); //20  

因此,由于这个copy对象只是对第一层进行拷贝,无法拷贝深层的对象,这个copy为浅拷贝,对象的子对象也是引用,所以遍历赋值的时候要判断,子元素是否是对象,如果子元素是对象,则继续对子元素进行遍历赋值,我们需要通过递归,来拷贝深层的对象。

  var obj = {a:{b:10}};
  function deepCopyObj(obj){
      if(typeof obj != 'object'){
          return obj;
      var newobj = {};
      for ( var attr in obj) {
          newobj[attr] = deepCopyObj(obj[attr]);
      return newobj;
  var obj2 = deepCopyObj(obj);
  obj2.a.b = 20;
  alert(obj.a.b); //10  

对象引用做为函数参数传递

对象引用做为函数参数传递时候,依然会相互影响,切记,如下示例:

var data = {a:1,b:2,c:3,d:{q:4,w:5,e:6}}; var data1 = data; function con(data2){ data2["r"] = 5; console.log(JSON.stringify(data2)); con(data1); console.log(JSON.stringify(data)); 输出结果: {"a":1,"b":2,"c":3,"d":{"q":4,"w":5,"e":6},"r":5} {"a":1,"b":2,"c":3,"d":{"q":4,"w":5,"e":6},"r":5}

对象引用赋值后,如果将对象置空,相互不受影响

  var arr = {"a":"1","b":"2"};
  var arr1 = arr;
  arr = {};
  arr["a"] = 2;
  console.log(arr1);
  console.log(arr);
输出结果:{"a":"1","b":"2"},{"a":2}

函数的克隆

var x=function(){alert(1);};
var y=x;
y=function(){alert(2);};
// function(){alert(1);};
alert(x);
// y=function(){alert(2);};
alert(y);

函数的克隆,使用“=”符号就可以了,并且在改变克隆后的对象,不会影响克隆之前的对象,因为克隆之后的对象会单独复制一次并存储实际数据的,是真实的克隆。

完整的对象克隆

  function clone(obj) {
    var o,i,j,k;
    if(typeof(obj)!="object" || obj===null)return obj;
    if(obj instanceof(Array)) {
      o=[];
      j=obj.length;
      for(;i<j;i++)  {
        if(typeof(obj[i])=="object" && obj[i]!=null) {
          o[i]=arguments.callee(obj[i]);
        } else {
          o[i]=obj[i];
    }else {
      o={};
      for(i in obj){
        if(typeof(obj[i])=="object" && obj[i]!=null){
          o[i]=arguments.callee(obj[i]);
        }else{
          o[i]=obj[i];
    return o;
最后编辑于:2018-01-18 12:00