三目运算、对象克隆、浅拷贝、深拷贝(十四)

2020/6/20 JS

# 一、三目运算

条件(三元)运算符: 一个条件后面会跟一个(?),如果条件为真,则(?)后面的表达式A将会执行; 表达式A后面跟着一个(:),如果条件为假,则(:)后面的表达式B将会执行。 本运算符经常作为if语句的简捷形式来使用。

var a = 5;
if (a > 0) {
  console.log('大于0');
} else {
  console.log('小于等于0');
}

a > 0 ? console.log('大于0')
      : console.log('小于等于0'); 

//-------------------------------------------------------------------------

// 字符串根据ASCII码按位比较
/**
 *	89 > 9 -> true 执行括号内的语句
 *	'89' > '9' -> false '8'的ASCII码小于'9'的ASCII码 执行:后面的表达式
 *	str = '内层未通过'
 */
var str = 89 > 9 ? ('89' > '9' ? '通过了'
                               : '内层未通过'
                   )
                   : '外层未通过';

console.log(str);   // '内层未通过'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 二、对象克隆

Object.prototype.num = 1;
var person1 = {
  name: '张三',
  age: 18,
  sex: 'male',
  height: 180,
  weight: 140,
  son: {
    first: 'Jenney',
    second: 'Lucy',
    Third: 'Jone'
  }
}

// person1和person2指向同一对象
var person2 = person1; // person2指向person1的地址
// 修改person2的name属性
person2.name = '李四'; 
console.log(person1, person2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 三、浅拷贝

Object.prototype.num = 1;
var person1 = {
  name: '张三',
  age: 18,
  sex: 'male',
  height: 180,
  weight: 140,
  son: {
    first: 'Jenney',
    second: 'Lucy',
    Third: 'Jone'
  }
}
// 字面量创建对象
var person2 = {};
// 浅拷贝
for (var key in person1) {
  // 把person1的可枚举属性赋值给person2(包括原型上的属性)
  person2[key] = person1[key];
}

// 在浅拷贝过程中,原始值复制的是副本,两个变量完全独立,互不干扰
person2.name = '李四';
// 在浅拷贝过程中,引用值复制的是指针,两个变量指向同一对象
person2.son.forth = 'Ben';
console.log(person1, person2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 封装浅拷贝

function clone(origin, target) {
  // 没传入target时,声明一个空对象
  var target = target || {};
  for (var key in origin) {
    // 过滤掉原型上的属性
    if (origin.hasOwnProperty(key)) {
      target[key] = origin[key];
    }
  }
  return target;
}
1
2
3
4
5
6
7
8
9
10
11

# 四、深拷贝

Object.prototype.num = 1;
var 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) {
  // 没传入target时,声明一个空对象
  var target = target || {},
  //	保存对象原型上toString方法
  toStr = Object.prototype.toString,
  //	保存对象原型上数组调用toString方法的返回值
  arrType = '[object Array]';
	// 枚举源对象上的可枚举属性(包括原型上的可枚举属性)
  for (var key in origin) {
    // 过滤掉原型上的属性,只拷贝自身可枚举属性
    if (origin.hasOwnProperty(key)) {
      // 当属性是引用值,且不为null时,条件为真
      if ((typeof(origin[key]) === 'object') && origin[key] !== null) {
        // 当前引用值调用对象原型toString方法判断是否是数组
        if(toStr.call(origin[key]) === arrType) {
          // 声明一个空数组,进行递归
          target[key] = [];
        } else {
          // 声明一个空对象,进行递归
          target[key] = {};
        }
        // 要克隆的属性是引用值,需要递归
        deepClone(origin[key], target[key])
      } else {
        // 原始值直接复制
        target[key] = origin[key];
      }
    }
  }
  // 返回深拷贝结果
  return target;
}
// 将深拷贝结果赋值给person2
var person2 = deepClone(person1);
// 修改对象的原始值
person2.name = '李四';
// 修改对象的引用值
person2.car = ['BMW'];
console.log(person1, person2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 封装深拷贝

function deepClone(origin, target) {
  var target = target || {},
  toStr = Object.prototype.toString,
  arrType = '[object Array]';

  for (var key in origin) {
    if (origin.hasOwnProperty(key)) {
      if ((typeof(origin[key]) === 'object') && origin[key] !== null) {
        if(toStr.call(origin[key]) === arrType) {
          target[key] = [];
        } else {
          target[key] = {};
        }
        deepClone(origin[key], target[key])
      } else {
        target[key] = origin[key];
      }
    }
  }
  return target;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 五、笔试题

/**
 * AO = {
 * foo: undefined -> 2
 * }
 */
function test() {
  console.log(foo); // undefined
  var foo = 2;
  console.log(foo); // 2
  console.log(a); // ReferenceError
}

test();
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * AO = {
 * test: undefined -> function test() {console.log(1)}
 * }
 */
function a() {
  var test;
  test();
  function test() {
    console.log(1); // 执行
  }
}
a();
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * GO = {
 * name: undefined -> '222'
 * a: undefined -> {
 *    name: '111',
 *    say: function () {
 *        console.log(this.name)
 * }
 * }
 * fun: undefined -> function () {...}
 * b: undefined -> {
 *  name: '333',
 *  say: function (fun) {...}
 * }
 * }
 */
var name = '222';
var a = {
  name: '111',
  say: function () {
    console.log(this.name);
  }
}

var fun = a.say;
fun(); // '222'
a.say(); // '111'
var b = {
  name: '333',
  say: function (fun) {
    fun();
  }
}
b.say(a.say); // '222'
b.say = a.say;
b.say(); // '333'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * AO = {
 * marty: undefined -> {
    name: 'marty',
    printName: function () {
      console.log(this.name);
    }
 * test1: undefined -> {
    name: 'test1'
  }
 * test2: undefined -> {
    name: 'test2'
  }
 }
 * test3: undefined -> {
    name: 'test3',
    printName: function () {
      console.log(this.name);
    }
  }
 * }
 */
function test() {
  var marty = {
    name: 'marty',
    printName: function () {
      console.log(this.name);
    }
  }

  var test1 = {
    name: 'test1'
  }
  var test2 = {
    name: 'test2'
  }
  var test3 = {
    name: 'test3'
  }

  test3.printName = marty.printName;
  marty.printName.call(test1); // 'test1'
  marty.printName.apply(test2); // 'test2'
  marty.printName(); // 'marty'
  test3.printName(); // 'test3'
}

test();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 * GO = {
 *  bar: undefined -> {
 *  a: '1' -> 'a'
 *  Object.prototype.b = 'b'
 * }
 *  test: function test() {...}
 * }
 * 
 */
var bar = {
  a: '1'
}

function test() {
  bar.a = 'a';
  Object.prototype.b = 'b';
  return function inner() {
    console.log(bar.a);
    console.log(bar.b);
  }
}
test()(); // 'a' 'b'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * GO = {
 *  getName: function () {
      console.log(4);
    }
 *  Foo: function Foo() {
 *    getName = function () {
 *    console.log(2)
 *    }
 *  }
 * Foo.prototype = {
 *  getName = function () {
    console.log(3);
      }
 *  }
 * }
 */
function Foo() {
  getName = function () {
    console.log(1);
  }
  return this;
}

Foo.getName = function () {
  console.log(2);
}
Foo.prototype.getName = function () {
  console.log(3);
}
var getName = function () {
  console.log(4);
}
function getName() {
  console.log(5);
}

Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Last Updated: 2022/7/21 10:52:53
Genshin Impact bgm
Genshin Impact