三元运算符、对象克隆、深浅拷贝
三元运算符
- 三元运算符基础
// 三元运算符
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()();
\