综合习题
狐七 3/22/2022 running
# 1. js引用类型
下面代码输出什么?
var a = {n: 1}
var b = a
a.x = a = {n: 2}
console.log(a.x)
console.log(b.x)
1
2
3
4
5
2
3
4
5
查看答案
结果
undefined
{n: 2}
- a 和 b 同时引用了 {n: 2} 对象
- 执行到 a.x = a = {n: 2} 语句
- 尽管赋值是从右到左的没错,但是.的优先级比=要高,所以这里首先执行a.x,相当于为 a所指向的{n: 1}对象新增了一个属性x,即此时对象将变为 { n: 1, x: undefined }
- 之后按正常情况,从右到左进行赋值,此时执行 a = {n: 2} 的时候,a的引用改变,指向了新对象{n: 2},而b依然指向的是旧对象
- 之后执行 a.x = {n: 2} 的时候,并不会重新解析一遍a,而是沿用最初解析a.x时候的a,也即旧对象,故此时旧对象的x的值为{n: 2},旧对象为 { n: 1, x: {n: 2} },它被b引用着。
- 访问 a.x 的时候,又要解析a了,此时的a是指向新对象的a,而这个新对象是没有x属性的,故访问时输出 undefined
- 访问 b.x 的时候,将输出旧对象的x的值,即{n: 2}
# 2. js类型
下面代码输出什么?
// example 1
var a = {},
b = '123',
c = 123;
a[b] = 'b';
a[c] = 'c';
console.log(a[b]);
// example 2
var a = {},
b = Symbol('123'),
c = Symbol('123');
a[b] = 'b';
a[c] = 'c';
console.log(a[b]);
// example 3
var a = {},
b = {
key: '123'
},
c = {
key: '456'
};
a[b] = 'b';
a[c] = 'c';
console.log(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
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
查看答案
- example 1: 'c'
- example 2: 'b'
- example 3: 'c'
查看解析
- 对象的键名只能是字符串和 Symbol 类型。
- 其他类型的键名会被转换成字符串类型。
- 对象转字符串默认会调用 toString 方法。
// example 1
- c的键名会被转换成字符串'123',这里会把b覆盖掉,输出'c'
// example 2
- b 是 Symbol 类型,不需要转换
- c 是 Symbol 类型,不需要转换
- 任何一个 Symbol 类型的值都是不相等的, 所以不会覆盖掉b,输出'b'
// example 3
- b 不是字符串也不是 Symbol 类型,需要转换成字符串。对象类型会调用 toString 方法转换成字符串 [object Object]
- c 不是字符串也不是 Symbol 类型,需要转换成字符串。对象类型会调用 toString 方法转换成字符串 [object Object]
- 所以这里会把 b 覆盖掉,输出'c'
# 3. js引用类型2
下面代码输出什么?
function changeObjProperty(o) {
o.siteUrl = "http://www.baidu.com"
o = new Object()
o.siteUrl = "http://www.google.com"
}
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
查看答案
// http://www.baidu.com
- webSite 属于复合数据类型,函数参数中以地址传递,修改值会影响到原始值。
- 但是之后o指向了新的地址,修改了新的地址的值,原值没有收到影响。
- 所以输出的是
http://www.baidu.com
# 4. 类
请写出如下代码的打印结果
function Foo() {
Foo.a = function () {
console.log(1);
};
this.a = function () {
console.log(2);
};
}
Foo.prototype.a = function () {
console.log(3);
};
Foo.a = function () {
console.log(4);
};
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
查看答案
// 4 2 1
- 第一个 Foo.a() 是调用Foo的静态方法,因为构造函数没有调用,所以内部方法没有执行,所以会执行外面的4
- 第二个 obj.a() 是实例化的Foo,调用a会先查找内部ownProperty,再去找原型链,所以这里输出2
- 第三个 Foo.a() 构造函数已经调用,内部方法优先级高,已经覆盖同名的静态方法,所以会执行内部1
# 5. 隐式类型转换
请写出如下代码的打印结果
const foo = {
toString () {
return 'xm'
},
valueOf () {
return 1
}
}
console.log(1+foo)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
查看答案
// 2
- 加法运算符,foo对象会调用其toString方法或者valueOf方法,所以我们经常会通过改变这两种方法控制加法的运算结果。
- 如果只有toString则会输出1xm,如果只有valueOf则会输出2,如果两者都有,这道题valueOf优先。