JS笔试题总结

1 . 字符串翻转

var str = "abcdefghijk";
console.log(str.split('').reverse().join(''))
//输出:kjihgfedcba

split()将字符串变成数组,reverse()将数组翻转,join将数组变成字符串

2 . 数组去重

		var str = "abcdabcaba";  //给定字符串
        var strArr = str.split("");  //将字符串分割成数组
        var NewArr = []; 			//创建新数组,用来保存去重后的值
        for (let i in strArr) {		//切记使用let声明,let证明的变量只在当前作用域中生效
            if (NewArr.indexOf(strArr[i]) == -1) { 
            //indexOf()判断指定值在数组中的下标,如果等于 - 1 这说明该数组中没有这个值
                NewArr.push(strArr[i])
            //NewArr中没有这个值就把这个值添加进来,组成新数组,也就是去重数组
            }
        }
        console.log(NewArr);
        //输出:["a", "b", "c", "d"]

数组去重的本质是利用 indexOf 检测新数组中是否存在被去重数组中的值,没有的话就加入,有的话就进行下一次循环。

		var Arr = ["a", "a", "a", "a", "b", "c", "d", "e", "f", "g", "k", "l"];
        var newArr = new Set(Arr)
        console.log([...newArr]);
        //ES6 新增 Set 方法
        //Set类似于数组(但不是数组所以要把它转化成数组),区别在于它所有的成员都是唯一的,不能有重复的值

数组去重的衍生,有两个小写字符串str1 、str2 。str2 是 str1 经过打乱后增加几个小写字符得到的, 编程得出s2中增加的字符

		var str1 = "abcdefg"
        //["a", "b", "c", "d", "e", "f", "g"]
        var str2 = "caflkebgdaaa"
        //["a", "a", "a", "a", "b", "c", "d", "e", "f", "g", "k", "l"]  
        var newstr1 = str1.split("").sort();
        var newstr2 = str2.split("").sort();
        var tempArr = [];
        for(let i in newstr2){
            if(newstr1.indexOf(newstr2[i]) == -1){
                tempArr.push(newstr2[i]) ;
            }
            else{
                newstr1.splice(0,1);
                //splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
                //arrayObject.splice(index,howmany,item1,.....,itemX)
                //splice() 参数,index表示删除的位置索引,howmany表示往索引后删除几个
            }
        }
        console.log(tempArr);
        //["a", "a", "a", "k", "l"]

3 . JS二分查找(binary_search)

二分法查找,是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:
(1)首先,从有序数组中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
(2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
(3)如果某一步数组为空,则表示找不到目标元素。

//非递归算法
		function binary_search(arr, key) {  //传入参数,要查找的有序数组,要查找的值
            var low = 0,			//设置最左端查找区间的值
                high = arr.length - 1;		//设置最右端查找区间的值
            while(low <= high){		//左边小于右边时
                var mid = parseInt((high + low) / 2);	//设置二分查找的中间值
                if(key == arr[mid]){	//如果要查找的值 == 数组中间值
                    return  mid;		//返回值,并结束循环
                }else if(key > arr[mid]){  //如果要查找的值 > 数组中间值,说明要查找的值在数组右半边
                    low = mid + 1;		//设置最左端查找区间的值 设置为中间值+1,从右侧开始查找
                }else if(key < arr[mid]){  //如果要查找的值 < 数组中间值,说明要查找的值在数组右半边
                    high = mid -1;		//设置最右端查找区间的值 设置为中间值-1,从左侧开始查找
                }else{
                    return -1;		//整个数组都没找到,返回 -1 并结束循环
                }
            }
        };
        var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
        var result = binary_search(arr,10);
        console.log(result); // 9 (9为目标元素的索引值  )     
// 递归算法,其实就是代替了while循环
        function binary_search(arr,low, high, key) {
            if (low > high){
                return -1;
            }
            var mid = parseInt((high + low) / 2);
            if(arr[mid] == key){
                return mid;
            }else if (arr[mid] > key){
                high = mid - 1;
                return binary_search(arr, low, high, key);
            }else if (arr[mid] < key){
                low = mid + 1;
                return binary_search(arr, low, high, key);
            }
        };
        var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
        var result = binary_search(arr, 0, 13, 10);
        console.log(result); // 9 返回目标元素的索引值 

4 . 闭包相关题目

什么是闭包?闭包的定义:闭包是指有权访问另外一个函数作用域 中的变量的函数,可以理解为(能够读取其他函数内部变量的函数)
闭包的作用: 正常函数执行完毕后,里面声明的变量被垃圾回收处理掉,但是闭包可以让作用域里的变量,在函数执行完之后依旧保持没有被垃圾回收处理掉
闭包的优点:

1 . 避免全局变量的污染。
2 . 可以实现私有成员的存在。
3 . 可以使一个变量长期存储在内存中。

闭包的缺点:

1 . 常驻内存,增加内存使用量。
2 . 使用不当会很容易造成内存泄露。

// 创建闭包最常见的方式函数作为返回值,举个最经典例子,计数器的例子
		function outAdd() {
            var counter = 0;	//函数内部定义变量,不能被函数外访问到
            
            function innerAdd() {	//这里的 innerAdd 就是我们所谓的闭包
                return counter += 1;
            }
            
            return innerAdd;	//返回整个函数,注意千万不能加()
        }
        
        var add = outAdd();   //注意这里为什么要将 outAdd 赋值给一个变量(重点)
        add();  // 1
        add();  // 2
        add();  // 3
        add();  // 4

在这里插入图片描述
这样在执行完 add = outAdd()后,变量 add 实际上是指向了函数 innerAdd,innerAdd 中用到了变量counter ,再执行 add () 后就会显示 counter 的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数 outAdd 外的变量 add 引用了函数 outAdd 内的函数 innerAdd 。
他一共运行 4 次,第一次值 1,第二次值为 2,这就说明 counter 一直在内存中,而不是在第一次 outAdd 函数调用之后就自动清除。

5 . 变量提升及函数声明先于变量声明

		console.log(a)       //       undefined
        var a = 1;
        var getNum = function () {
            a = 2;
        }
        function getNum() {
            a = 3;
        }
        console.log(a)      //        1
        getNum()
        console.log(a)      //        2

这题主要考察变量提升函数声明优先于变量声明

// JS预解析阶段,变量提升,且函数提升优先于变量提升
        function getNum() {
            a = 3;
        }
        var a;              //实质为var a = undefined;
        var getNum;         //实质为var getNum = undefined;

        // 执行代码
        console.log(a);     //输出undefined
        a = 1;              //实质为var a = undefined;变成 var a = 1;
        //实质执行了var getNum = function(){a=2};
        //由于变量声明无法覆盖函数声明,一开始getNum指向一个函数,后来赋值成了一个函数表达式,指向了另一个函数。
        getNum = function () {  
            a = 2;
        }

        console.log(a)      //此时 a 变成了 1 
        getNum()            //执行getNum函数
        console.log(a)      //此时函数指向已改变,输出 a = 2

6 . 闭包和 js执行机制 的考察 每隔大概一秒输出一次 i 值

		for (var i = 0; i < 5; i++) {
            setTimeout(function (i) {
                console.log(i)
            }, i * 1000, i)  //setTimeout()的三个参数,第一个为需要延迟执行的代码段
            				 //第二个参数为延迟多久执行,单位毫秒1000ms = 1s
            				 //第三个参数为传递到延迟执行代码段中的参数
        }
		for(let i = 1; i < 5; i++) {
		    setTimeout(function(){
		        console.log(i)
		    }, i * 1000)
		}

主要有两点注意点,var 声明的变量个 let 声明的变量以及 异步执行 的问题
var 声明的变量存在变量提升,而 let 声明的变量有只在当前作用域生效的特点

		for (var i = 0; i < 4; i++) {
		  setTimeout(function() {
		    console.log(i);
		  }, 1000);
		}
		//这里很多人认为会输出:0,1,2, 3,实际输出 4 个 4
		//原因是 setTimeout 是个异步执行程序,他会等同步任务执行完之后,再从任务队列中拿出来运行
		//而此时的 i 已经在最后一次 for 循环结束后变成了 4 
		//稍微更改一下,把 var 变成 let
		for (let i = 0; i < 4; i++) {
		  setTimeout(function() {
		    console.log(i);
		  }, 300);
		}
		//输出 0 1 2 3 
		//原因是 let  声明的变量有只在当前作用域生效的特点,也就是说每次 for 循环都会创建一个独立的作用域,此时 let 声明的变量只能在当前作用域中被使用

for 循环 和 let 连起来使用可以避免很多麻烦, let 和 for 循环应用实例

		//创建10个 a 标签 , 点击标签 显示对应标签的序号
		for (let i = 0; i < 10; i++) {
           var a = document.createElement("a");		//创建一个元素 a
           document.body.appendChild(a);			//将元素插入页面中
           a.innerHTML = (i+1) + '<br>';			//a 标签 序号 + 换行
           a.addEventListener('click',function(){	//添加点击事件
                console.log(i+1);
           })
       }

7 . 字符串转化为驼峰式

		var str1 = 'get-element-by-id'
        var arr1 = []
        var arr2 = str1.split('-')   //把数组转化成字符串
        //console.log(arr2)
        for (let i in arr2) {		// for...in  语句用于遍历数组或者对象的属性
            var letter = arr2[i].replace(arr2[i][0], arr2[i][0].toUpperCase())
            //arr2[i][0] 表示第 i 个元素的 第 0 个值 
            //string.replace( searchvalue , newvalue )
            //searchvalue 要替换的字符   newvalue 替换后的字符
            arr1.push(letter)
            //将其添加到预先声明好的空数组里
        }
        var str2 = arr1.join('')
        //join()  将数组转化成字符串
        console.log(str2)

replace() 字符串替换
toUpperCase() 大写
replaceFirst() 替换遇到的第一个字符串

猜你喜欢

转载自blog.csdn.net/qq_40893035/article/details/105932005