JS三元运算符、对象克隆、深浅拷贝

150 阅读3分钟

三元运算符、对象克隆、深浅拷贝

三元运算符

  • 三元运算符基础
 // 三元运算符
 let a = 5,
   str = "";
 if (a > 0) {
   console.log("大于0");
 } else {
   console.log("小于等于0");
 }
 // 三段式的if语句可以使用三元运算符
 // 写成下面这种
 ​
 str = a > 0 ? "大于0" : "小于等于0";  // 三元运算符有return功能的
  • 三元运算符嵌套
 // 三元运算符嵌套的问题
 let a = 5,
   str = "";
 if (a > 0) {
   if (a > 3) {
     str = "大于3";
   } else {
     str = "小于等于3";
   }
 } else {
   str = "小于等于0";
 }
 //转换成三元运算符
 str = a > 0 ? (a > 3 ? "大于3" : "小于等于3") : "小于等于0";
  • 三元运算符面试题
 // 面试题
 let str =
   89 > 9 ? ("89" > "9" ? "通过了" : "内层未通过") : "外层未通过";
 // str = '内层未通过' 
 // 因为字符串相比较看的是ASC码的值 8 小于 9 所以直接返回内层未通过

对象克隆

 // 拷贝/复制/克隆
 let person1 = {
   name: "张三",
   age: 18,
   sex: "male",
   height: 180,
   weight: 140,
 };
 let person2 = person1;
 person2.name = "李四";
 console.log(person1, person2); // name都是'李四'
 // 本质就是新变量指向之前对象的存储空间

浅拷贝

 //浅拷贝
 let person1 = {
   name: "张三",
   age: 18,
   sex: "male",
   height: 180,
   weight: 140,
   son: {
     first: "Jenney",
     second: "Lucy",
     Third: "Jone",
   },
 };
 //把老对象的属性循环添加到新对象里
 let person2 = {};
 for (let key in person1) {
   person2[key] = person1[key];
 }
 console.log(person1, person2); //内容一样地址不同
 // 浅拷贝只处理了原始值,没有处理引用值,所以如果更改引用值还是会影响双方
  • 浅拷贝只循环拷贝对象的第一层原始值,假如对象中有引用值则直接拷贝引用值地址。
  • 所以如果更改引用值的属性,则拷贝对象与被拷贝对象都会发生改变

封装浅拷贝

 // 用方法写浅拷贝
 function clone(origin, target) {
   let tar = target || {};
   for (let key in origin) {
     if (origin.hasOwnProperty(key)) {
       tar[key] = origin[key];
     }
   }
 }
 return tar;

深拷贝

 // 原始对象
 let person1 = {
   name: "张三",
   age: 18,
   sex: "male",
   height: 180,
   weight: 140,
   children: {
     first: {
       name: "张小一",
       age: 13,
     },
     second: {
       name: "张小二",
       age: 7,
     },
     third: {
       name: "张小三",
       age: 3,
     },
   },
   car: ["Benz", "Mazda"],
 };
 ​
 ​
 // 深拷贝
 ​
 function deepClone(origin, target) {
   let target = target || {}, // 初始化
     toStr = Object.prototype.toString; // 把判断数据的toString方法保存到变量里
   arrType = "[object Array]"; // 数组的输出值
   for (let key in origin) { // 遍历原始对象
     if (origin.hasOwnProperty(key)) { // 判断这个属性是否为原始对象本身属性而不是原型上的属性
       if (typeof (origin[key] === "object") && origin[key] !== null) { // 判断属性是否为引用值,历史问题null也会被判断为object所以需要排除
         if (toStr.call(origin[key]) === arrType) { // 判断是否为数组
           target[key] = []; 
         } else { // 不是数组就是对象
           target[key] = {};
         }
         deepClone(origin[key], target[key]); // 递归
       } else {
         target[key] = origin[key]; // 出口
       }
     }
   }
   return target;
 }
  • 深拷贝则是用递归的方式,遇到引用值则继续调用自己,直到所有属性都是原始属性则拷贝后退出
  • 这样修改引用值属性不会影响原始对象

用JSON实现深拷贝

 // 用JSON深拷贝
 let str = JSON.stringify(person1);
 console.log(str); // 把对象完全转化成字符串
 let person2 = JSON.parse(str); // 把字符串转化成对象
  • 如果原始对象内有方法则这个方式不可用

面试题

  • 第一题
// 笔试题1
function test() {
  console.log(foo); // undefined
  var foo = 2;
  console.log(foo); // 2
  console.log(a); //报错
}
test();
  • 第二题
function a() {
  var test;
  test();
  function test() {
    console.log(1);
  }
}
a(); // 打印1
  • 第三题
// 阿里面试题
var name = "222";
var a = {
  name: "111",
  say: function () {
    console.log(this.name);
  },
};
var fun = a.say();
// var fun = function(){
//  console.log(this.name); 这里的this指向window 是222
// }
fun(); // '222'
a.say(); // '111'
var b = {
  name: "333",
  say: function (fun) {
    fun();
  },
};

b.say(a.say); //'222'
// 这里this指向的全局

b.say = a.say;

b.say(); // '333'
  • 第四题
function test() {
  var marty = {
    name: "marty",
    printName: function () {
      console.log(this.name);
    },
  };
  var test1 = {
    name: "test1",
  };
  var test2 = {
    name: "test2",
  };
  var test3 = {
    name: " test3",
    /*   printName: function () {
      console.log(this.name);
    }, */
  };
  test3.printName = marty.printName;
  marty.printName.call(test1); //test1
  marty.printName.apply(test2); // test2
  marty.printName(); // marty
  test3.printName(); // test3
}
  • 第五题
var bar = {
  a: "1",
};
function test() {
  bar.a = "a";
  Object.prototype.b = "b";
  return function inner() {
    console.log(bar.a); //a
    console.log(bar.b); //b
  };
}
test()();

\