js基础算法题
正则
1、给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false
// 在正则表达式中,利用()进行分组,使用斜杠加数字表示引用,\1就是引用第一个分组,
// \2就是引用第二个分组。将[a-zA-Z]做为一个分组,然后引用,就可以判断是否有连续重复的字母。
function containsRepeatingLetter(str) {
return /([a-zA-Z])\1/.test(str);
}
console.log(containsRepeatingLetter('abaaaa') );
2、给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false
function containsNumber(str) {
return /\d/.test(str)
}
3、给定字符串 str,检查其是否以元音字母结尾。元音字母包括 a,e,i,o,u,以及对应的大写,包含返回 true,否则返回 false
function endsWithVowel(str) {
return /[aeiou]$/ig.test(str)
}
4、字符串中是否含有连续的三个任意数字,如果包含,返回最新出现的 3 个数字的字符串,如果不包含,返回 false
function captureThreeNumbers(str) {
var arr = str.match(/\d{3}/);
if(arr){
return arr[0];
}else{
return false;
}
}
5、给定字符串 str,检查其是否符合如下格式:XXX-XXX-XXXX,其中 X 为 Number 类型
function matchesPattern(str) {
return /^\d{3}-\d{3}-\d{4}$/.test(str);
}
6、给定字符串 str,检查其是否符合美元书写格式
1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用 , 分隔
3、如果为小数,则小数部分长度为 2
4、正确的格式如:$1,023,032.03 或者 $2.03 $0.12,错误的格式如:$3,432,12.12 或者 $34,344.3
将整数部分和小数部分作为一个整体,在整数部分又将逗号和3个数字作为整体
function isUSD(str) {
var re = /^\$([1-9]\d{0,2}(,\d{3})*|0)(\.\d{2})?$/;
return re.test(str);
}
对象
1、将函数 fn 的执行上下文改为 obj,返回 fn 执行后的值
function alterContext(fn, obj) {
return fn.call(obj)
}
function alterContext(fn, obj) {
return fn.apply(obj)
}
function alterContext(fn, obj) {
return fn.bind(obj)()
}
2、给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量
function alterObjects(constructor, greeting) {
constructor.prototype.greeting = greeting;
}
3、找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)
1、返回数组,格式为 key: value
2、结果数组不要求顺序
Object.keys(obj)----返回实例的可枚举的属性组成的数组,结合map(fn)
for....in(对象所有可枚举的属性,包括原型),obj.hasOwnProperty(prop)----属性prop是对象实例的属性返回true
Object.getOwnPropertyNames(obj)----返回实例的属性(包括不可枚举的)组成的数组
// Object.keys 方法,返回可枚举的实例属性的数组
function iterate(obj) {
return Object.keys(obj).map(function(key) {
return key + ": " + obj[key];
});
}
// for...in遍历所有可枚举的属性,包括原型上的
// hasOwnProperty()检测是否在属性上,是返回true
function iterate(obj) {
const res = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
res.push(prop + ": " + obj[prop]);
}
}
return res;
}
// Object.getOwnPropertyNames(),返回的是所有实例属性的数组(包括不可枚举的)
function iterate(obj) {
return Object.getOwnPropertyNames(obj).map(function(key) {
return key + ": " + obj[key];
});
}
Number
1、获取数字 num 二进制形式第 bit 位的值。注意:----将十进制转成二进制利用num.toString(2)
1、bit 从 1 开始
2、返回 0 或 1
3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1
function valueAtBit(num, bit) {
//toString转化为二进制,split将二进制转化为数组,reverse()将数组颠倒顺序
var arr = num.toString(2).split("").reverse();
return arr[bit-1];
}
2、给定二进制字符串,将其换算成对应的十进制数字---parseInt(str,进制)
function base10(str) {
/**
其它进制转十进制
parseInt(str,2)
parseInt(str,8)
parseInt(str,16)
*/
return parseInt(str,2);
}
3、将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位
function convertToBinary(num) {
var str = num.toString(2);
while(str.length < 8) {
str = "0" + str;
}
return str;
}
模块
完成函数 createModule,调用之后满足如下要求:
1、返回一个对象
2、对象的 greeting 属性值等于 str1, name 属性值等于 str2
3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ', ' + name属性值
// 构造函数+原型模式
function createModule(str1, str2) {
function Obj()
{
this.greeting = str1;
this.name = str2;
}
Obj.prototype.sayIt = function(){return this.greeting + ", " + this.name;}
return new Obj();
}
// 构造函数
function createModule(str1, str2) {
function Obj()
{
this.greeting = str1;
this.name = str2;
this.sayIt = function(){return this.greeting + ", " + this.name;}
}
return new Obj();
}
// 工厂模式
function createModule(str1, str2) {
function CreateObj()
{
obj = new Object;
obj.greeting = str1;
obj.name = str2;
obj.sayIt = function(){return this.greeting + ", " + this.name;}
return obj;
}
return CreateObj();
}
// 对象字面量形式
function createModule(str1, str2) {
var obj =
{
greeting : str1,
name : str2,
sayIt : function(){return this.greeting + ", " + this.name;}
};
return obj;
}
函数
1、柯里化
已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件:
1、返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数)
2、调用 a 之后,返回一个函数 b, b 的 length 属性值为 1
3、调用 b 之后,返回一个函数 c, c 的 length 属性值为 1
4、调用 c 之后,返回的结果与调用 fn 的返回值一致
5、fn 的参数依次为函数 a, b, c 的调用参数
3个参数
const curry = (fn)=>{
if( typeof(fn) !=='function' ){
throw Error('argument is error');
}
let len = fn.length;
return function curried(...arg){
if(arg.length<len){
return (...arg1)=>curried.apply(null,arg.concat(arg1))
}else{
return fn.apply(null,arg);
}
}
}
// let sum = curry((a,b,c)=>a+b+c);
console.log( curry((a,b,c)=>a+b+c)(1)(2,3));
2、实现函数 partialUsingArguments---二次封装函数,调用之后满足如下条件:
1、返回一个函数 result
2、调用 result 之后,返回的结果与调用函数 fn 的结果一致
3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数
function partialUsingArguments(fn) {
//先获取p函数第一个参数之后的全部参数
var args = Array.prototype.slice.call(arguments,1);
//声明result函数
var result = function(){
//使用concat合并两个或多个数组中的元素
return fn.apply(null, args.concat([].slice.call(arguments)));
}
return result;
}
3、实现函数 callIt----使用apply调用函数,调用之后满足如下条件
1、返回的结果为调用 fn 之后的结果
2、fn 的调用参数为 callIt 的第一个参数之后的全部参数
function callIt(fn) {
var arg = [].slice.call(arguments,1);
return fn.apply(null,arg);
}
4、使用arguments
函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换
function useArguments() {
var arg = [].slice.call(arguments);
return arg.reduce(function(sum,item){ return sum+item },0);
}
5、二次封装函数
已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致
// call和apply必须显式地调用str3,立即执行
// bind不是立即执行,未传入str3时,并未执行,只是返回一个函数,等待参数传入
// this用于上下文不确定的情况
// call
function partial(fn, str1, str2) {
return function(str3) {
return fn.call(this, str1, str2, str3);
}
return result;
}
// apply(这里只是为了对照)
function partial(fn, str1, str2) {
return function (str3) {
return fn.apply(this, [str1, str2, str3]);
}
}
// 这个bind会生成一个新函数(对象), 它的str1, str2参数都定死了, str3未传入, 一旦传入就会执行
function partial(fn, str1, str2) {
return fn.bind(this, str1, str2); // 或 return fn.bind(null, str1, str2);
}
// 匿名函数,默认this绑定global,与bind的第一个参数为this时效果一样。
function partial(fn, str1, str2) {
return function(str3) {
return fn(str1, str2, str3);
}
}
// ES6。this指向undefined.
const partial = (fn, str1, str2) => str3 => fn(str1, str2, str3);
6、闭包
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同
function makeClosures(arr, fn) {
var result = arr.map(function(item){
return function(){
return fn(item);
}
})
return result;
}
7、返回函数
实现函数 functionFunction,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', '
3、所有函数的参数数量为 1,且均为 String 类型
function functionFunction(str) {
return function(str2){
return str + ', ' + str2
}
}
流程控制
实现 fizzBuzz 函数,参数 num 与返回值的关系如下:
1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz
2、如果 num 能被 3 整除,返回字符串 fizz
3、如果 num 能被 5 整除,返回字符串 buzz
4、如果参数为空或者不是 Number 类型,返回 false
5、其余情况,返回参数 num
function fizzBuzz(num) {
if(isNaN(num)){
return false;
}
var str='';
if(num%3===0){
str+='fizz';
}
if(num%5===0){
str+='buzz';
}
return str||num; ||当两个数里面有一个不是boolean类型,如果左边为对象则返回左边的对象,否则返回右边的值
}
计数器
// setTimeout
function count(start, end) {
if(start <= end){
console.log(start);
start++;
st = setTimeout(function(){count(start, end)}, 100);
}
return {
cancel: function(){clearTimeout(st);}
}
}
// setInterval
function count(start, end) {
//立即输出第一个值
console.log(start++);
var timer = setInterval(function(){
if(start <= end){
console.log(start++);
}else{
clearInterval(timer);
}
},100);
//返回一个对象
return {
cancel : function(){
clearInterval(timer);
}
};
}
数组
1、查找重复元素
//对数组的每一个元素遍历
//通过indexOf()和lastIndexOf()索引不同并且在存放结果的数组里面没有该元素
//则为新的重复元素
function duplicates(arr) {
var result = [];
arr.forEach(function(elem){
if(arr.indexOf(elem) !=arr.lastIndexOf(elem) && result.indexOf(elem) == -1){
result.push(elem);
}
});
return result;
}
2、统计数组 arr 中值等于 item 的元素出现的次数
function count(arr, item) {
return arr.toString().match(new RegExp(item,"g")).length;
}
3、在数组 arr 的 index 处添加元素 item。不要直接修改数组 arr,结果返回新的数组
function insert(arr, item, index) {
return arr.slice(0,index).concat(item,arr.slice(index))
}
4、移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回
function removeWithoutCopy(arr, item) {
for(var i = 0; i < arr.length; i++){
if(arr[i] == item){
//splice方法会改变数组长度,当减掉一个元素后,后面的元素都会前移,因此需要相应减少i的值
arr.splice(i,1);
i--;
}
}
return arr;
}
5、移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组
function remove(arr,item){
return arr.filter(function(ele){
return ele != item;
})
}