js常见笔试题

1、影响原数组的方法

push(): 向数组末尾添加一个或多个元素。
pop(): 删除数组末尾的元素,并返回被删除的元素。
shift(): 删除数组头部的元素,并返回被删除的元素。
unshift(): 向数组头部添加一个或多个元素。
splice(): 根据索引删除指定位置的元素,并可选地插入新的元素。
sort(): 排序数组中的元素。
reverse(): 颠倒数组中的元素的顺序。

es6中数组的扩展有,解构赋值、扩展运算符...、includes、find,findIndex、Array.from()、Array.of()

2、typeof常见题目:

toypeof null的值OBject

3、数字和字符串类型转换

1、数字转字符串
	Number类定义的toString()方法
	Number类定义的toFixed()方法
	使用String()函数:
2、字符串转数字
	通过Number()转换函数
	parseInt()函数
	parseFloat()函数

4、正则表达式基本:

* :出现零到多次
+: 出现一到多次
?:出现零次或者一次
 .  : 除了\n以外的任意字符
{n} : 出现n次
{n,} : 出现n到多次
{n,m} : 出现n到m次

5、++x是前置自增,也就是先自增加1,再将x返回

6、深拷贝实现

手写递归方法:(递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝)
  function cloneDeep(obj) {
  	//数据类型为引用数据类型
  	if (typeof obj == 'object') {
  		//初始化返回结果
		let result = Array.isArray(obj) ? [] : {};
		fot(let key in obj) {
			//避免相互引用出现死循环导致爆栈
			if (obj === obj[key]) {
				continue
			}
			if (obj.hasOwnProperty(key)) {
				//递归调用
				result[key] = deepClone(obj[key])
			}
		}
		return result
  	} else {
  		//基本数据类型,直接返回
  		return obj
  	}
  }
//下面是各种都考虑到了
function deepCopy(obj, parent = null) {
    // 创建一个新对象
    let result = {};
    let keys = Object.keys(obj),
        key = null,
        temp = null,
        _parent = parent;
    // 该字段有父级则需要追溯该字段的父级
    while (_parent) {
        // 如果该字段引用了它的父级则为循环引用
        if (_parent.originalParent === obj) {
            // 循环引用直接返回同级的新对象
            return _parent.currentParent;
        }
        _parent = _parent.parent;
    }
    for (let i = 0; i < keys.length; i++) {
        key = keys[i];
        temp = obj[key];
        // 如果字段的值也是一个对象
        if (temp && typeof temp === 'object') {
            // 递归执行深拷贝 将同级的待拷贝对象与新对象传递给 parent 方便追溯循环引用
            result[key] = DeepCopy(temp, {
                originalParent: obj,
                currentParent: result,
                parent: parent
            });

        } else {
            result[key] = temp;
        }
    }
    return result;
}


还有问题:子对象互相引用的情况没有解决

7、版本号对比实现

function compareVersion(version1, version2) {
    const v1 = version1.split('.');
    const v2 = version2.split('.');
    for (let i = 0; i < v1.length || i < v2.length; i++) {
        let x = 0, y = 0;
        if (i < v1.length) {
            x = parseInt(v1[i]);
        }
        if (i < v2.length) {
            y = parseInt(v2[i])
        }
        if (x > y) return 1;
        if (x < y) return -1;
    }
    return 0;
}
let v1 = '3.34.5', v2 = '3.27.10';
console.log(compareVersion(v1, v2));

8、严格等于非严格等于与Object.is():

下列表达式中,返回值为true的是()

①Object.is(NaN,NaN)

②Object.is(+0,-0)

③NaN === NaN

④+0 === -0

A
①④

9、防抖

防抖的实现原理是,当事件被触发 n 秒后才会执行回调函数,如果在这 n 秒内该事件又被触发,则重新计时。这种方法可以有效防止事件的过多触发,常用于输入框搜索和滚动事件等。

function debounce(func, wait) {
    let timeout;
    return function() {
        const context = this;
        const args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(function() {
            func.apply(context, args);
        }, wait);
    };
}

// 调用方式
const debounceFn = debounce(function() {
    console.log('debounce');
}, 1000);
document.addEventListener('scroll', debounceFn);

我们定义了函数 debounce,它接受两个参数,一个是回调函数 func,一个是等待时间 wait。返回的是一个匿名函数。在匿名函数内部,我们定义了变量 timeout,用于保存定时器的返回值。当事件被触发时,我们清除该定时器,并重新设置一个新的定时器以达到延迟执行的效果。最后返回的是一个函数,该函数每次执行时都会先清除定时器,然后再设置一个新的定时器,来达到防抖的效果。

10、节流

节流的原理是规定在一个单位时间内,只能触发一次函数。如果这个时间段内触发多次函数,只有一次能生效。常用于滚动事件、resize 事件等。

function throttle(func, wait) {
    let timeout;
    return function() {
        const context = this;
        const args = arguments;
        if (!timeout) {
            timeout = setTimeout(function() {
                func.apply(context, args);
                timeout = null;
            }, wait);
        }
    };
}

// 调用方式
const throttleFn = throttle(function() {
    console.log('throttle');
}, 1000);
document.addEventListener('scroll', throttleFn);

我们定义了函数 throttle,它接受两个参数,一个是回调函数 func,一个是等待时间 wait。返回的是一个匿名函数。在匿名函数内部,我们定义了变量 timeout,用于保存定时器的返回值。当事件被触发时,如果定时器不存在,则创建一个新的定时器,并在单位时间结束后执行回调函数,否则不做任何处理。最后返回的是一个函数,该函数每次执行时会判断定时器是否存在,只有不存在时才会创建新的定时器。

11、递归

递归是一种函数调用自身的方式。在算法和数据结构中经常用到。

function fibonacci(n) {
  if (n < 2) {
    return n;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(10)); // 55

使用递归将多为数组对象转化为一维数组对象,详细代码如下:
function flatten(arr) {
  var result = [];
  for (var i = 0, len = arr.length; i < len; i++) {
    if (Array.isArray(arr[i])) {
      result = result.concat(flatten(arr[i]));
      // 递归展开嵌套数组
    } else {
      result.push(arr[i]);
    }
  }
  return result;
}
flatten 函数中通过 for 循环遍历数组中的每一项,如果当前项是一个数组,
就递归调用 flatten 函数再次将其展开;否则就将当前项 push 到结果数组中。例子如下
var arr = [1, [2, [3, 4], 5], 6];
var result = flatten(arr);
console.log(result); // [1, 2, 3, 4, 5, 6]

我们定义了函数 fibonacci,它接受一个参数 n,表示要求得 fibonacci 的第 n 项。当 n 小于 2 时,直接返回 n,否则返回前两项之和。该函数在执行时会不断调用自身,直到 n 小于 2 为止。这就是递归的基本实现方式。

12、数据去重

数据去重是指去除重复的数据。在开发中,常用于数组去重等场景。

方法一:使用 Set
const arr = [1, 1, 2, 2, 3, 4, 4, 5];
const set = new Set(arr);
const result = Array.from(set);

console.log(result); // [1, 2, 3, 4, 5]
我们将数组转换成了 Set 类型,并将 Set 转成了数组,得到了去重后的结果。
方法二:使用 filter
const arr = [1, 1, 2, 2, 3, 4, 4, 5];
const result = arr.filter(function(item, index, array) {
    return array.indexOf(item) === index;
});

console.log(result); // [1, 2, 3, 4, 5]

这里我们使用了 filter 函数,它有三个参数分别为当前元素、当前元素索引和原数组。在 filter 函数内部,我们使用数组的 indexOf 方法来判断当前元素是否已经存在于数组中,如果是则返回 true,否则返回 false。最终过滤出的结果即为去重后的数组。

13、数据排序

数据排序是指将数据按照一定的规则进行排序。在开发中,我们常用的排序算法有冒泡排序、快速排序、归并排序等。

冒泡排序
function bubbleSort(arr) {
    for (let i = 0; i < arr.length - 1; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                const tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
    return arr;
}

const arr = [3, 2, 5, 4, 1];
console.log(bubbleSort(arr)); // [1, 2, 3, 4, 5]

我们定义了函数 bubbleSort,它接受一个数组 arr,并使用嵌套循环的方式实现了冒泡排序。在内层循环中,我们使用 if 语句来判断相邻的两个元素的大小,如果前面的元素比后面的元素大,则交换它们的位置。在内层循环结束后,我们得到了最大的元素,它被放在了数组的最后面。然后我们再进行下一轮循环,直到所有的轮次循环完成。

快速排序
function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    const pivotIndex = Math.floor(arr.length / 2);
    const pivot = arr.splice(pivotIndex, 1)[0];
    const left = [];
    const right = [];
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] < pivot) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    return quickSort(left).concat([pivot], quickSort(right));
}

const arr = [3, 2, 5, 4, 1];
console.log(quickSort(arr)); // [1, 2, 3, 4, 5]

我们定义了函数 quickSort,它接受一个数组 arr

14、统计字符串中字符出现最多的字符以及相应的数量

var str = "stiabsstringapbs";
 var obj = {};
 for (var i = 0; i < str.length; i++) {
          var key = str[i];
               if (!obj[key]) {
                   obj[key] = 1;
              } else {
                   obj[key]++;
                }
  }
  var max = -1;
  var max_key = "";
  var key;
  for (key in obj) {
           if (max < obj[key]) {
                     max = obj[key];
                     max_key = key;
         }
 }
   alert("max:"+max+" max_key:"+max_key);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一些常见的Web前端笔试题题库的介绍: 1. LeetCode:LeetCode是一个在线的编程题库,其中包含了大量的算法和数据结构题目。虽然主要面向算法工程师,但也有一些与前端开发相关的题目,如字符串处理、数组操作等。通过解决这些题目,可以提升编程能力和思维逻辑。 2. HackerRank:HackerRank是一个全球性的技术招聘平台,提供了丰富的编程题目和挑战。它包含了各种难度级别的前端开发题目,涵盖了HTML、CSS、JavaScript等方面的知识点。通过完成这些题目,可以加深对前端技术的理解和应用。 3. Codewars:Codewars是一个以编程挑战为主题的在线社区。它提供了各种难度级别的编程题目,包括前端开发相关的题目。在Codewars上,你可以与其他开发者进行交流和比拼,提高自己的编码能力。 4. Frontend Masters:Frontend Masters是一个在线学习平台,提供了大量的前端开发课程和练习题。它的题库涵盖了HTML、CSS、JavaScript等方面的知识点,并且难度适中。通过学习和完成这些练习题,可以系统地提升前端开发技能。 5. FreeCodeCamp:FreeCodeCamp是一个免费的在线学习平台,专注于教授编程和Web开发技术。它提供了一系列的前端开发项目和挑战,涵盖了HTML、CSS、JavaScript等方面的知识点。通过完成这些项目和挑战,可以锻炼实际开发能力。 希望以上介绍对你有帮助!如果你还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值