题目:有时候我们需要访问一个对象较深的层次,但是如果这个对象某个属性不存在的话就会报错,例如:
1 | var data = { a: { b: { c: 'ScriptOJ' } } } |
请你完成一个 safeGet 函数,可以安全的获取无限多层次的数据,一旦数据不存在不会报错,会返回 undefined,
例如:1
2
3
4var data = { a: { b: { c: 'ScriptOJ' } } }
safeGet(data, 'a.b.c') // = scriptoj
safeGet(data, 'a.b.c.d') // = 返回 undefined
safeGet(data, 'a.b.c.d.e.f.g') // = 返回 undefined
答案1:
1 | const safeGet = (o, path) = { |
答案2:
1 | function safeGet(o, path){ |
shvl
1 | npm install --save shvl |
1 | export function get (object, path, def) { |
USE
1 | import * as shvl from 'shvl'; |
ES7可选链式调用
1 | console.log(data.user?.address?.street) //undefined |
题目如下:
1 | function Parent() { |
知识点
原型链的查找规则
- 当实例上存在属性时, 用实例上的
- 如果实例不存在,顺在原型链,往上查找,如果存在,就使用原型链的
- 如果原型链都不存在,就用Object原型对象上的
- 如果Object原型对象都不存在, 就是undefined
- 数组和字面量对象都是引用
this指向在引用时确认而不是定义时
解题思路
下面分别模拟Q1-Q6的执行情况
Q1:
直接调用
parent.show()
,此时this指向parent,语句中的三条语句相当于分别在给window对象上赋值:1
2
3parent.a = 1;
parent.b = [1, 2, parent.a];
parent.c = { demo: 8 };
此时,parent对象应为:
1 | { |
Q2:
在执行var child1 = new Child();
语句时,child对象的a值为2,而因为后被手动赋值为11,所以child实例上的a被改为11,这时调用原型链上的show()
方法,依次打印,
这里this.a
根据原型链的查找规则,在实例上有a的赋值,所以直接使用实例上的值也就是11,其他值实例上没有,需要在原型上寻找,所以输出b为[1,2,this.a]
,
而这里的this.b因为是数组,为引用类型,在执行var parent = new Parent();
时被定义在parent实例上,所有this.a的指针指向共同的引用地址,所以为1 ,
this.c因为也是引用类型,指针也被指向共同的引用对象地址。
Q3:
实例上的a被重新赋值,所以this.a
的输出被改为12,其余执行步骤同Q2。
Q4:
相当于再次调用parent实例上的show方法,因为数据没有发生变动,所以输出值同Q1。
Q5:
因为在调用this.change
时,this.a的值被赋值为this.b数组的长度,所有这里的a输出为4,this.b的值使用引用地址b数组,因为在下一步中又执行了一次对this.b数组的push,所以这里打印this.b是被push两次后的数组,而this.c也是被push两次后的数组的长度,注意因为this.a和this.c的数据类型不同,所以this.a是单独的内存,而this.c则是使用相同一块内存。
Q6:
又对this.b数组执行了一次push,所以这次this.a的输出应为数组的当前长度也就是5,this.c的值也是数组长度也就是5。
答案
在chrome控制台中运行代码得到结果如下: