Javascript面试题(第二部分)

一进入到文章就看到9题开头到小伙伴,因为我这里是第二部分了,所以说还有第一部分,当然因为我自己做到题库是没有顺序到,所以你们可以直接从第二部分来看.

9. js 的typeof返回有哪些数据类型?

typeof 是用来检测数据类型到,但是注意它返回的是字符串,如图1所示是typeof可以返回到数据类型

number,string,boolean,object,symbol,undefined,function
typeof返回的数据类型

从图1可以看到有7种, 注意array和null都是object. 而function依旧是function,此外我们来验证一些问题就是number要不要大写,那么我直接看typeof返回的结果吧,如图2所示,返回数据类型的结果.

<script>
    console.log(typeof 1);
    // -> number 

    console.log(typeof '1');
    // -> string 

    console.log(typeof function fn(){
     
     });
    // -> function
    
    console.log(typeof null);
    // -> object

    console.log(typeof undefined);
    // -> undefined

    console.log(typeof Symbol());
    // -> symbol
    
    console.log(typeof true);
    // -> boolean
</script>
图2.返回数据类型的结果.

从图2可以知道, typeof返回的类型不是随便写的,如果随便写一旦用于某种判断的时候就可能会让你得重新浏览下问题或看出错提示了, 很直观的可以看到所有结果都是小写

10. 什么是闭包?为什么要用它?

闭包

这是一个100%会问的面试题. 因为他涉及了函数式编程等知识的运用.

3.8 闭包

闭包就是将函数视为值的能力,以及每次调用函数时都重新创建(函数中的)局部绑定的事实. 如图3所示:闭包

function wrapValue(local = n) {
    
    
    return () => local;
}

let wrap1 = wrapValue(1)
let wrap2 = wrapValue(2)
console.log(wrap1());
// -> 1
console.log(wrap2());
// -> 2

console.log(wrap1() + wrap2());
// -> 3
图3.闭包

可以看到两个绑定的实例,很好地证明了每次调用都会重新创建局部绑定的事实,并且不同的调用不能在其他调用的局部绑定上进行操作.
这种能够引用封闭作用域中局部绑定的特定实例的功能称为闭包.引用其周围局部作用域的绑定的一个函数称为一个闭包.

在这里经常会问的就是闭包的使用场景,我之前有写过好像.以后我再提供一下.

那么继续刚才图3的例子,进行一些修改,让他可以变得可以更具创造性点,如图4所示: 创建乘以任何数量的函数

function multiplier(factor) {
    
    
    return number => number * factor
}

let twice = multiplier(2)
console.log(twice(4));
// -> 8
图4.创建乘以任何数量的函数

关键在于let twice = multiplier(2) 需要乘以其他数就传进去即可,这种歌思想是需要一定程度练习才可以掌握的. 一个好的思路模型是将函数值视为同时包含其函数体内的代码和创建它们的环境.调用时,函数体会看到创建它的环境,而不是调用它的环境
在图4的例子中,调用multiplier并创建一个将其factor参数定为2的环境.它返回的函数值(存在twice中)会记住此环境.因此,当调用twice时,它将其参数乘以2.

闭包优缺点和作用

闭包优点:缓存数据
闭包缺点:内存泄漏,溢出
闭包作用:自执行函数 不会污染全局变量 形成块级作用域 变量私有化

闭包应用场景

其实我们已经在许多地方使用了闭包,只是没注意,可以看这篇文章闭包应用场景

11. 简述js继承的方式

因为JS继承也是一个频繁使用到,但是对于初学者可能很少会注意到的知识点, 阅读下该文章js实现继承的几种方式后我在另外写一篇稀有度极高的JavaScript的继承方式. 这篇文章我还没有仔细去写,因为用到的地方也不是很多.

12.如何实现深拷贝

面试手写题.深拷贝应用场景的文章不多,书上也很少提及到,但是还是需要掌握的.参考文章深拷贝
为了提高读者的兴趣,笔者在这里说一个例子来说说深浅拷贝区别:我们常常看到化妆师,化妆师可以给一个人化妆,可以化的外表一模一样.但是动作却复制不来.而深拷贝就是可以将动作,性格统统复制过去. 并且不会影响到被复制的对象.另外可以从对象就是有属性和方法的去理解.

传值和传址

传值和传址是拷贝的基础概念

传值: 变量A赋值给变量B,修改变量B不会修改到变量A
如图5所示:传值.

let str = 'xh';
let str2 = str; // 传值
str2 = 'heihei'; // 新变量修改了值,不会影响原来变量的值
console.log(str,str2);
// -> xh heihei
图5:传值

传址: 和传值类似,但是不同的地方是,修改其中一个两个都会同时更改,因为地址共享. 如图6所示:传址

let obj = {
    
    
     name:'xh',
     subject:['数学','地理']
 }
 let obj1 = {
    
    }
 // 开始赋值和修改
 obj1 = obj
 obj1.subject = ['英语']
 obj1.name = 'alv'
 console.table(obj1); 
 // -> 修改obj1的时候obj的属性值也被修改了.
 console.table(obj);
图6:传址

传值是简单数据类型,传址是复杂数据类型

简单数据类型和复杂数据类型

简单数据类型(基础类型, 原始类型): Number、String、Boolean、Undefined、Symbol(SE6新增的);
引用类型(复杂类型, 复合类型):Object(Math、Nul、Function{ Array、Set、Map、Date、RegExp } );

深拷贝实现

因为浅拷贝不能解决下一层的一个拷贝所以需要采用深拷贝.
深拷贝之后2个变量就会相互独立不再彼此影响.
实现原理: 对数组/对象进行拷贝,使用递归循环复制.每次递归都开辟新的内存地址(指针),所以一般只要不是同一内存地址,就不会修改其值.

深拷贝方式一:JSON.parse(JSON.stringify( )) 序列化

如图7所示: JSON深拷贝
适用于:数组、对象数组、数组对象

let myArr = ["HTML", ["CSS", "H5", ["html", "head", ["meta", "title", "style"], "body"], "CSS3"], "ES6", "jQuery"]
let copyArr = JSON.parse(JSON.stringify(myArr))
copyArr[1][2][2][2] = 'change'
console.log(copyArr[1][2][2][2]);
// -> change
console.log(myArr[1][2][2][2]);
// -> style
图7: JSON深拷贝

到这里,基本已经满足业务开发的需求了. 下面还有其他的深拷贝模式,最后再来看下优缺点,在昨天的面试中我遇见了这么一道深拷贝的题,也不止一次了。所以今天一定要掌握,此外还遇见了Promise的题目,到时候也要针对性强化。

深拷贝方式二:deepCopy函数

如图8所示: deepCopy函数
适用于:数组、对象数组、数组对象

<script>
        // 判断是否是数组
        function isArrayHandle(arr){
     
     
            return Object.prototype.toString.call(arr) === "[object Array]";
        }

        // 判断是否是对象 
        function isObjHandle(obj){
     
     
            return typeof obj === "object" && obj !== null;
        }

        function deepCopy(val){
     
     
            let oVal = isArrayHandle(val) ? [] : {
     
     } // 在最开始就要决定是对象还是数组
            for(let v in val){
     
     
                if(isObjHandle(val[v])){
     
     
                    // 递归关键
                    oVal[v] = deepCopy(val[v])
                }else{
     
     
                    oVal[v] = val[v]
                }
            }
            return oVal;
        }
    </script>
图8: deepCopy函数

猜你喜欢

转载自blog.csdn.net/qq_25953937/article/details/109896473