让前端面试不在难(三)

6次阅读

共计 2531 个字符,预计需要花费 7 分钟才能阅读完成。

今天聊一下 clone 这个前端面试高频问题,由此引出 typeof、instanceof、Object.prototype.toString 这些 javascript Api。
下面我们先详细的聊一下,完了解决下面试官的问题。
typeof
typeof 能获取一个变量或表达式的类型。

原始类型

Boolean
Null
Undefined
String
Symbol
Number
Symbol

和 引用类型 Object,Function

下面看一些栗子
// 基础类型也可以说非引用类型
let str = ‘hello word!’
console.log(typeof str) //string
let num = 12
console.log(typeof num) //number
let udf = undefined
console.log(typeof udf) //undefined
let bl = true
console.log(typeof bl) //boolean
let nl = null
console.log(nl) //null
let sl = Symbol()
console.log(typeof sl) //symbol

// 复合类型也可以说是引用类型,
let obj = {
a: 1
}
console.log(typeof obj) //object
let arr = [1, 2, 3]
console.log(typeof arr) //object

// 函数也属于引用类型,不过 typeof 却能准确的返回类型
function fn() {}
console.log(typeof fn) //function
从以上的执行结果可以看出,typeof 不能够准确分返回所有类型
instenceof
我们从 instenceof 的实现来了解下 instenceof 是干什么的
// 模拟 instenceof 实现
// 1、instenceof 接收两个参数
// 2、返回 true 或 false

function myInstenceof(X, Y) {
let L = X._proto_
let R = Y.prototype
if (L !== R) {
return false
}
return true
}

// test
function Fn() {

}
let newFn = new Fn()
console.log(newFn)
console.log(new Fn())

console.log(myInstenceof(newFn, new Fn())) //true
console.log(myInstenceof([], new Array())) //true
console.log(myInstenceof([], new Object())) //true

以上 demo 我们就能看出,instenceof 也不够靠谱,模拟实现就是判断 X 的原型知否在 Y 的原型链上。数组之所以 instenceof Object 为 true 是因为 [].prototype->new Array->new Object->null
上边说了 typeof 和 instenceof 其实就是想说这两个对于深度 clone 的实现来说不够严谨要不就是多层判断。
Object.prototype.toString.call()
接下里我们说个靠谱的
Object.prototype.toString.call(”); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]
Object.prototype.toString.call(document); // [object HTMLDocument]
Object.prototype.toString.call(window); //[object Window]
靠谱!
接下来我们就用 Object.prototype.toString.call() 来解答一下面试题
function clone(obj, o) {
//Object.prototype.toString.call(obj) 返回类似 [Object Array] 利用 slice 来截取我们需要的字符串
let type = Object.prototype.toString.call(obj).slice(8, -1)
// 如果是 Object
if (type === ‘Object’) {
o = {}
for (let k in obj) {
o[k] = clone(obj[k]);
}
// 如果是对象
} else if (type === ‘Array’) {
o = []
for (let i = 0; i < obj.length; i++) {
o.push(clone(obj[i]));
}
} else {
// 非引用类型
o = obj
}
return o
}

let obj1 = {
a: [1, 2, 3, 4, 5, 6],
b: {
c: 2
},
d: 1,
f: function() {
return 1
}
}
let obj2 = clone(obj1)
obj2.f = function() {
return 2
}
obj2.a = 1
console.log(obj1)
console.log(obj2)
测试打印结果,obj2 的改变不会影响到 obj1。
欢迎吐槽!

正文完
 0