前端面试笔试题
最编程
2024-02-29 20:31:03
...
1-实现(5).add(3).minus(6)输出6
(function () {
function check(n) {
n = Number(n);
return isNaN(n) ? 0 : n;
}
function add(n) {
n = check(n);
return this + n;
}
function minus(n) {
n = check(n);
return this - n;
}
["add", "minus"].forEach((item) => {
Number.prototype[item] = eval(item);
});
})();
console.log((5).add(3).minus(2));
2-自行编写each方法
//
let arr = [10, 20, 30, "aa", 40],
obj = {};
Array.prototype.each = function (...arg) {
let arr = [];
if (arg[1]) {
for (let i = 0; i < this.length; i++) {
if (arg[0].call(arg[1], this[i]) == false) {
break;
}
arr.push(arg[0].call(arg[1], this[i]));
}
} else {
for (let i = 0; i < this.length; i++) {
if (arg[0](this[i]) == false) {
break;
}
arr.push(arg[0](this[i]));
}
}
return arr;
};
arr = arr.each(function (item) {
if (isNaN(item)) {
return false;
}
return item * 10;
});
console.log(arr); //[ 100, 200, 300 ]
3-将字符串的大小写进行翻转
var str = "哈哈哈hhhLLL";
str = str.replace(/[a-zA-Z]/g, (content) => {
return content.toUpperCase() === content //如果转换成大写之后等于原先的字符即原先的字符就是大写
? content.toLowerCase()
: content.toUpperCase();
});
console.log(str);
4-编写与indexof功能相同的函数
(function () {
function myIndexOf(T) {
// let lenT = T.length,
// lenS = this.length,
// res = -1;
//if(lenT<lenS){
// for (let i = 0; i <= lenS - lenT; i++) {
// if (this.substr(i, lenT) === T) {
// res = i;
// break;
// }
// }
//}
// return res;
let reg = new RegExp(T);
res = reg.exec(this);
return res === null ? -1 : res.index;
}
String.prototype.myIndexOf = myIndexOf;
})();
let S = "zzzzsssssaaaaa",
T = "sa";
console.log(S.myIndexOf(T));
5-对象的属性
var a = {},
b = { key: "123" },
c = { key: "456" };
a[b] = "b";
a[c] = "c";
console.log(a); //c
/*
因为在对象的属性中,对象的属性会自动调用该属性原型上的toString()方法转换为字符串
而任何 对象.toString=='[object Object]'
*/
var a = {},
b = Symbol("123"),
c = Symbol("123");
a[b] = "b";
a[c] = "c";
console.log(a); //b
/* Symbol创建的值是唯一的 */
var a = {},
b = "123",
c = 123;
a[b] = "b";
a[c] = "c";
console.log(a); //c
/* 因为在对象的属性中,对象的属性会自动调用该属性原型上的toString()方法转换为字符串
因此在这里 123.toString() == '123'*/
6-对象
function Foo() {
Foo.a = function () {
console.log(1);
};
this.a = function () {
console.log(2);
};
}
//在原型上设置实例共有的属性方法,只有实例才能使用
Foo.prototype.a = function () {
console.log(3);
};
//把Foo当做普通对象设置私有的属性方法
Foo.a = function () {
console.log(4);
};
Foo.a(); //4
let obj = new Foo();
obj.a(); //2 //自身有,可以不往构造函数的原型上找
Foo.a(); //1 有了实例才能用实例里面的方法
7-正则验证给单词前后加空格
let str = "no哈哈哈h,ho,好借好还",
reg = /\b[a-z]+\b/gi;
str = str.replace(reg, (value) => {
return " " + value + " ";
});
console.log(str);
8-数组扁平化
//数组扁平化并除去其中重复部分数据,最终得到一个升序且不重复的数组
// 1.
let arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, [13, 14, [19, 20]]], 10];
// arr = [...new Set(arr.flat(Infinity).sort((a, b) => a - b))];
//2.
// arr = [
// ...new Set(
// arr
// .toString()
// .split(",")
// .map((item) => Number(item))
// .sort((a, b) => a - b)
// ),
// ];
// console.log(arr);
// 3.
// arr = [
// ...new Set(
// JSON.stringify(arr)
// .replace(/(\[|\])/g, "")
// .split(",")
// .map((item) => Number(item))
// .sort((a, b) => a - b)
// ),
// ];
// console.log(arr);
// 4.
// while (arr.some((item) => Array.isArray(item))) {
// arr = [].concat(...arr);
// }
// console.log(arr);
// 5.
~(function () {
function myFlat() {
let result = [],
fn = (arr) => {
for (let index = 0; index < arr.length; index++) {
let item = arr[index];
if (Array.isArray(item)) {
fn(item);
continue;
} else {
result.push(item);
}
}
};
fn(this);
return result;
}
Array.prototype.myFlat = myFlat;
})();
arr = arr.myFlat();
console.log(arr);
9-自写new
/*
new一个实例的时候发生了什么?
+ 像普通函数执行一样,形成一个私有的作用域
-形参赋值
-变量提升
+ 默认创建一个对象,让函数中的this执行这个对象,这个对象就是当前类的一个实例
+ 代码执行
+ 默认把创建的对象返回
*/
function Dog(name) {
this.name = name;
}
function _new(Fn, ...arg) {
// 1.
//创建一个空对象,让他的原型链指向Fn.prototype(作为Fn的一个实例)
// let obj = {};
// obj.__proto__ = Fn.prototype;
// 2.
let obj = Object.create(Fn.prototype);
Fn.call(obj, ...arg);
return obj;
}
Dog.prototype.saHi = function () {
console.log("hi");
};
let sanmao = _new(Dog, "三毛");
sanmao.saHi();
10-合并数组
let arr1 = ["A1", "A2", "B1", "B2", "C1", "C3", "D1"];
let arr2 = ["A", "B", "C"];
//实现合并后的数组为["A1", "A1","A" ,"B1", "B2","B", "C1", "C2","C", "D1"]
// arr2 = arr2.map((item) => item + "Z");
// arr1 = arr1
// .concat(arr2)
// .sort((a, b) => a.localeCompare(b))
// .map((item) => item.replace("Z", ""));
// console.log(arr1);
let index = null;
for (let i = 0; i < arr2.length; i++) {
for (let j = 0; j < arr1.length; j++) {
if (arr1[j].includes(arr2[i])) {
index = j;
}
}
if (index != null) {
arr1.splice(index + 1, 0, arr2[i]);
index = null;
}
}
console.log(arr1);
11-for和定时器
//由于使用var来定义的变量没有块级作用域。for循环中创建的定时器还没启动,for循环就已经完成,
//此时打印i则是调用全局的i,这时i=10;
/*for (var i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 100);
}*/
// 闭包解决
// for (var i = 0; i < 10; i++) {
// ~(function (i) {
// setTimeout(() => {
// console.log(i);
// }, 1000);
// })(i);
// }
// for (var i = 0; i < 10; i++) {
// // ~(function (i) {
// // setTimeout(() => {
// // console.log(i);
// // }, 1000);
// // })(i);
// setTimeout(
// ((i) => {
// return () => {
// console.log(i);
// };
// })(i),
// 1000
// );
// }
//使用bind,使用bind的预先处理机制,在循环的时候就把每次执行函数需要输出的结果,预先传递给函数即可
var fn = function (i) {
console.log(i);
};
for (var i = 0; i < 10; i++) {
setTimeout(fn.bind(null, i), 1000);
}
12-匿名函数起名字
// let fn = function AAA() {
// console.log(AAA);
// };
// fn();
// function fn() {
// console.log(fn);
// }
// console.log(fn);
var b = 10;
(function b() {
var b = 20;
console.log(b); //20
})();
console.log(b); //10
var c = 10;
(function c() {
c = 20;
console.log(c); //函数c
})();
console.log(c); //10
13-==进行比较时的操作
/*
==进行比较的时候,如果左右两边数据类型不一样,则先转换为相同的数据类型再进行比较
1. {}=={} 对象进行比较,比较的是堆内存的地址
2. null==undefined 相等 null === undefined 不相等
3. NaN和谁都不相等,包括NaN==NaN
4. 其他数据类型和字符串进行比较,把其他类型toString()后和字符串进行比较
5. 剩余所有情况在进行比较的时候都是转换为数字(前提是数据类型不同)
*/
// console.log({} == {});
// console.log(null == undefined);
// console.log(NaN == NaN);
// console.log([1] == "1");
// console.log([1] == true);
// var a = {
// n: 0,
// toString() {
// return ++this.n;
// },
// };
var a = [1, 2, 3];
a.toString = a.shift; //使其toString方法改变,调用自己的私有方法
if (a == 1 && a == 2 && a == 3) {
console.log(123);
}
15-push
let obj = {
2: 3,
3: 4,
length: 2,
push: Array.prototype.push,
};
obj.push(1);
obj.push(2);
console.log(obj);
//首先我们需要知道Array.prototype.push实现的时候进行了什么
/*
Array.prototype.push = function (val) {
this[this.length] = val;
return this.length;
};
*/
/*
如此可知在数组push的时候是将 this[this.length] = 新的值,并且这个数组的长度+1;
所以在这题中,
let obj = {
2: 1,
3: 2,
length: 4,
push: Array.prototype.push,
};
*/
16-冒泡排序
/*
冒泡排序思想: 让数组中的当前项和后一项进行比较,把值较大的放在后面.
最少要进行length-1轮比较,每轮比较都会把最大,次大,次三大..的值放到后面。
第一轮最多比较length-1次
第二轮最多比较length-2次
第三轮最多比较length-3此
.....
*/
let arr = [12, 8, 24, 16, 1];
function bubble(arr) {
// let temp = 0;
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]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
bubble(arr);
17-插入排序
/*
插入排序(抓扑克牌的排序)
首先先抓一张牌,再抓第二张牌,第二张牌和抓到的牌由后到头进行比较,在遇到比它小的牌就插
在这张牌的后面
*/
function insertSort(arr) {
let array = [];
array.push(arr[0]);
for (let i = 1; i < arr.length; i++) {
for (let j = array.length - 1; j >= 0; j--) {
if (array[j] <= arr[i]) {
array.splice(j + 1, 0, arr[i]);
break;
}
if (j === 0) {
array.unshift(arr[i]);
}
}
}
console.log(array);
return array;
}
insertSort([13, 8, 12, 1, 16, 0]);
18-快速排序
/*
arr=[24,8,9,6,15,2];
快速排序则是取中间的值,然后在arr中将该中间值去掉,使剩下的数值与该中间值进行比较
假设中间值是9
比9小的放到左数组,比9大的放到右数组
左数组:[8,6,2]
右数组:[24,15]
然后再对该左右数组取中间值,再分左右数组以此类推,直至剩下最后一个数,再将左右数组与中间数拼接
*/
function quickSort(arr) {
//4.结束递归,当arr中小于等于一项
if (arr.length <= 1) {
return arr;
}
//1.找到数组的中间项,在原有的数组中将它移除
let middleIndex = Math.floor(arr.length / 2);
let middleValue = arr.splice(middleIndex, 1)[0];
//2. 准备左右两个数组,循环剩下数组中的每一项
let left = [],
right = [];
for (let i = 0; i < arr.length; i++) {
arr[i] > middleValue ? right.push(arr[i]) : left.push(arr[i]);
}
//3. 递归让左右两边的数组持续这样处理,知道左右两边都排好序位置。(最后让左+中+右)
return quickSort(left).concat(middleValue, quickSort(right));
}
console.log(quickSort([24, 8, 9, 6, 15, 2]));
19-对象变数组
/*
某公司1-12月份的销售额如下
let obj = {
1: 222,
2: 123,
5: 888,
};
将其变成如下结构
[222,123,null,null,888,null,null,null,null,null,null]
*/
let obj = {
1: 222,
2: 123,
5: 888,
};
// 1.
// let arr = new Array(12).fill(null).map((item, index) => {
// return obj[index + 1] || null;
// });
// 2.
obj.length = 13;
let arr = Array.from(obj).slice(1);
console.log(arr);
arr = arr.map((item) => (item == undefined ? null : item));
console.log(arr);
20-旋转数组
/*
旋转数组
给定一个数组,将数组中的元素向右移动k个位置,其中k是非负数
输入:[1,2,3,4,5,6] k=3
输出: [5,6,7,1,2,3,4]
*/
function rotate(arr, k) {
if (k < 0 || k === 0 || k === arr.length) return arr;
if (k > arr.length) k = k % arr.length;
// for (let i = 0; i < k; i++) {
// arr.unshift(arr.pop());
// }
return arr.splice(arr.length - k).concat(arr);
}
console.log(rotate([1, 2, 3, 4, 5, 6, 7], 3));
21-实现add函数
/*
实现add函数满足以下功能
add(1); //1
add(1)(2);//3
add(1)(2)(3);//6
add(1)(2,3);//6
add(1,2)(3);//6
add(1,2,3);//6
函数柯理化:预先处理的思想(利用闭包的机制)
*/
//手写bind
// ~(function () {
// function myBind(context = window, ...outerArg) {
// let _this = this;
// return function (...innerArg) {
// _this.call(context, ...outerArg.concat(innerArg));
// };
// }
// Function.prototype.myBind = myBind;
// })();
// //利用闭包的保存作用,柯理化预先保存思想
// function fn(x) {
// return function (y) {
// return x + y;
// };
// }
// console.log(fn(100)(200));
function currying(fn, length) {
length = length || fn.length;
return function (...arg) {
if (arg.length >= length) {
return fn(...arg);
}
return currying(fn.bind(null, ...arg), length - arg.length);
};
}
// add = currying(add, 4);
let add = currying((...arg) => eval(arg.join("+")), 4);
// console.log(add(1));
console.log(add(1)(2)(3)(4));
// console.log(add(1, 2)(3, 4));
// add(1);
// add(1)(2)(3)(4);
上一篇: 社会招聘中级前端笔试面试问题汇总