🔥刷题秘籍!解锁JS高手之路:[牛客网]91道能力测评题攻略大全(一)

120 阅读28分钟

一、入门

1、dom 节点查找

描述:查找两个节点的最近的一个共同父节点,可以包括节点自身

输入描述:oNode1 和 oNode2 在同一文档中,且不会为相同的节点

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
 <div id="root">
   <div id="parent1">
     <div id="child1"></div>
     <div id="parent2">
       <div id="child2"></div>
    </div>
   </div>
 </div>
    <!-- 填写标签 -->
    <script type="text/javascript">
        function commonParentNode(oNode1, oNode2) {
            const ancestors1 = new Set();
          
           // 从oNode1向上遍历父节点链,并将每个父节点添加到Set中
            let currentNode = oNode1;
            while (currentNode) {
                ancestors1.add(currentNode);
                currentNode = currentNode.parentNode;
            }
          // 从oNode2向上遍历父节点链,检查每个父节点是否在ancestors1中存在
            currentNode = oNode2;
            while (currentNode) {
                if (ancestors1.has(currentNode)) {
                    return currentNode;// 如果找到共同的父节点,返回它
                }
                currentNode = currentNode.parentNode;
            }
        }
        const node1 = document.getElementById('child1');
        const node2 = document.getElementById('child2');
 
       const commonAncestor = commonParentNode(node1, node2);
       console.log(commonAncestor)//输出dom结构parent1
    </script>
</body>

</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
 <div id="root">
   <div id="parent1">
     <div id="child1"></div>
     <div id="parent2">
       <div id="child2"></div>
    </div>
   </div>
 </div>
    <!-- 填写标签 -->
    <script type="text/javascript">
        function commonParentNode(oNode1, oNode2) {
          //无须关心谁包含谁,只要当前节点的父节点包含另一个节点就行
             for(;oNode1;oNode1=oNode1.parentNode){
				if(oNode1.contains(oNode2)){
					return oNode1;
				}
			}
		}
   
        const node1 = document.getElementById('child1');
        const node2 = document.getElementById('child2');
 
       const commonAncestor = commonParentNode(node1, node2);
       console.log(commonAncestor)
    </script>
</body>

</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
 <div id="root">
   <div id="parent1">
     <div id="child1">
	 </div>
     <div id="parent2">
       <div id="child2"></div>
    </div>
   </div>
 </div>
    <!-- 填写标签 -->
    <script type="text/javascript">
       //验证一个节点是否包含另一个节点,否则拿到父节点重新进行验证
       function commonParentNode(oNode1, oNode2) {
        if(oNode1.contains(oNode2)){
            return oNode1;
        }else{
            return commonParentNode(oNode1.parentNode,oNode2);
        }
       } 
        const node1 = document.getElementById('child1');
        const node2 = document.getElementById('child2');
 
       const commonAncestor = commonParentNode(node1, node2);
       console.log(commonAncestor)
    </script>
</body>

</html>

2、根据包名,在指定空间中创建对象

描述:根据包名,在指定空间中创建对象

输入描述:namespace({a: {test: 1, b: 2}}, 'a.b.c.d')

输出描述:{a: {test: 1, b: {c: {d: {}}}}}

function namespace(namespaceObj, sPackage) {
      const arr = sPackage.split('.');
      let currentObj = namespaceObj;
      for(let i = 0;i<arr.length ;i++) {
        // 如果不是对象,则使它成为对象
        if(typeof currentObj[arr[i]] != 'object') {
          currentObj[arr[i]] = {};
        }
         currentObj = currentObj[arr[i]];
      }
      return namespaceObj;
} 

// 示例用法
const namespaceObj = {a: {test: 1, b: 2}};
const result = namespace(namespaceObj, 'a.b.c.d');
console.log(result);// 输出: { a: { test: 1, b: { c: { d: {} } } } }

3、斐波那契数列

描述:用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等

function fibonacci(n) {
   if(n<=2){
       return 1
   } else{
       return fibonacci(n-1) + fibonacci(n-2)
   }
}
console.log(fibonacci(1)); // 输出: 1
console.log(fibonacci(2)); // 输出: 1
console.log(fibonacci(3)); // 输出: 2
console.log(fibonacci(4)); // 输出: 3
console.log(fibonacci(5)); // 输出: 5
console.log(fibonacci(10)); // 输出: 55
 function fibonacci(n) {
    if (n <= 0) {
        throw new Error("Input should be a positive integer.");
    }
    if (n === 1 || n === 2) {
        return 1;
    }
    var num1 = 1, num2 = 1;
    for (var i = 3; i <= n; i++) { 
        var temp = num2; 
        num2 += num1; 
        num1 = temp;
    }
    return num2; 
}
console.log(fibonacci(1)); // 输出: 1
console.log(fibonacci(2)); // 输出: 1
console.log(fibonacci(3)); // 输出: 2
console.log(fibonacci(4)); // 输出: 3
console.log(fibonacci(5)); // 输出: 5
console.log(fibonacci(10)); // 输出: 55

4、计数

描述:统计数组 arr 中值等于 item 的元素出现的次数

示例:

输入:[1, 2, 4, 4, 3, 4, 3], 4

输出:3

    function count(arr, item) {
        let itemArr = arr.filter((num)=>{
               return num===item
        })
        return itemArr.length
    }
    let arr =[1, 2, 4, 4, 3, 4, 3];
    let item = 4;
    count(arr, item);
  function count(arr, item) {
    var num = 0;
    arr.forEach(function(a){
        if(a == item){
            num++;
        }
    });
    return num;
}
    let arr =[1, 2, 4, 4, 3, 4, 3];
    let item = 4;
    count(arr, item);
function count(arr, item) {
  let sum = 0
  for (let i = 0; i < arr.length; i++) {
      if(item === arr[i]){
          sum++
      }                
  }
  return sum 
}
let arr =[1, 2, 4, 4, 3, 4, 3];
let item = 4;
count(arr, item);
function count(arr, item) {
    return arr.filter(e=>e == item).length
}
let arr =[1, 2, 4, 4, 3, 4, 3];
let item = 4;
count(arr, item);

5、函数传参

描述:将数组 arr 中的元素作为调用函数 fn 的参数

示例:

输入:function (greeting, name, punctuation) {return greeting + ', ' + name + (punctuation || '!');},

['Hello', 'Ellie', '!']

输出:Hello, Ellie!

function argsAsArray(fn, arr) {
    return fn.apply(null, arr);  // 
}
let fn = function (greeting, name, punctuation) {
    return greeting + ', ' + name + (punctuation || '!');
}
let arr = ['Hello', 'Ellie', '!'];
console.log(argsAsArray(fn, arr));
let fn = function (greeting, name, punctuation) {
    return greeting + ', ' + name + (punctuation || '!');
}
let arr = ['Hello', 'Ellie', '!'];

// 直接使用扩展语法调用函数
console.log(fn(...arr));

6、函数的上下文

描述:将函数 fn 的执行上下文改为 obj 对象

示例

输入:function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'}

输出:Hello, Rebecca!!!

function speak(fn, obj) {
  return  fn.apply(obj)
}
let fn = function () {return this.greeting + ', ' + this.name + '!!!';}
let obj = {greeting: 'Hello', name: 'Rebecca'}
console.log(speak(fn, obj))
function speak(fn, obj) {
  return  fn.call(obj)
}
let fn = function () {return this.greeting + ', ' + this.name + '!!!';}
let obj = {greeting: 'Hello', name: 'Rebecca'}

console.log(speak(fn, obj))
function speak(fn, obj) {
  return  fn.bind(obj)()
}
let fn = function () {return this.greeting + ', ' + this.name + '!!!';}
let obj = {greeting: 'Hello', name: 'Rebecca'}

console.log(speak(fn, obj))
function speak(fn, obj) {
    obj.fn = fn
    return obj.fn()
}
let fn = function () {return this.greeting + ', ' + this.name + '!!!';}
let obj = {greeting: 'Hello', name: 'Rebecca'}

console.log(speak(fn, obj))

call()、bind()、apply()的用法,改变this的指向,区别在于:f.bind(obj, arg1, arg2,...)(),bind()方法创建一个新的函数,故需要自己调用;f.call(obj, arg1, arg2...),call()方法在调用函数后会返回函数的执行结果,call可以接受多个参数;f.apply(obj, [arg1, arg2, .]),apply()方法在调用函数后会返回函数的执行结果,apply可以接受一个数组参数列表。

7、二次封装函数

描述:

已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致

示例1

输入:var sayIt = function(greeting, name, punctuation) { return greeting + ', ' + name + (punctuation || '!'); }; partial(sayIt, 'Hello', 'Ellie')('!!!');

输出:

Hello, Ellie!!!

// 匿名函数,默认this绑定global,与bind的第一个参数为this时效果一样。
function partial(fn, str1, str2) {
     return function(str3){
           return fn(str1,str2,str3); 
      }
}
let fn = function(greeting, name, punctuation) {   
     return greeting + ', ' + name + (punctuation || '!');
};  
partial(fn, 'Hello', 'Ellie')('!!!');
function partial(fn, str1, str2) {
    function result(str3) {
        return fn.call(this, str1, str2, str3);
    }
 
     return result;
}
let fn = function(greeting, name, punctuation) {   
     return greeting + ', ' + name + (punctuation || '!');
};  
partial(fn, 'Hello', 'Ellie')('!!!');
function partial(fn, str1, str2) {
    function result(str3) {
        return fn.apply(this, [str1, str2, str3]);
    }
 
    return result;
}
let fn = function(greeting, name, punctuation) {   
     return greeting + ', ' + name + (punctuation || '!');
};  
partial(fn, 'Hello', 'Ellie')('!!!');
// 这个bind会生成一个新函数(对象), 它的str1, str2参数都定死了, str3未传入, 一旦传入就会执行
function partial(fn, str1, str2) {
    return fn.bind(this, str1, str2); ;
}
let fn = function(greeting, name, punctuation) {   
     return greeting + ', ' + name + (punctuation || '!');
};  
partial(fn, 'Hello', 'Ellie')('!!!');
function partial(fn, str1, str2) {
    function result(str3) {
        return fn.bind(this, str1, str2)(str3);
    }
 
    return result;
}
let fn = function(greeting, name, punctuation) {   
     return greeting + ', ' + name + (punctuation || '!');
};  
partial(fn, 'Hello', 'Ellie')('!!!');
var partial = (fn, str1, str2) => str3 => fn(str1, str2, str3);
//传统的函数表达式写法
//var partial = function(fn, str1, str2) {
  //  return function(str3) {
   //     return fn(str1, str2, str3);
  //  };
//};
let fn = function(greeting, name, punctuation) {   
     return greeting + ', ' + name + (punctuation || '!');
};  
partial(fn, 'Hello', 'Ellie')('!!!');

8、使用 arguments

描述:函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。

示例

输入:1, 2, 3, 4

输出:10

function useArguments() {
  let num = 0;
  for (let index = 0; index < arguments.length; index++) {
    num += arguments[index];
  }
  return num;
}
let arr =[1, 2, 3, 4];
console.log(useArguments(1, 2, 3, 4))
function useArguments(...args) {
    return args.reduce((count, num) => count + num, 0);
}

console.log(useArguments(1, 2, 3, 4)); // 输出 10
function useArguments() {
   return Array.prototype.reduce.call(arguments,function(acc,cur){
         return acc+=cur
   })
}
console.log(useArguments(1, 2, 3, 4))

9、柯里化

柯里化是将一个接收多个参数的函数,转变为一系列接收一个单一参数的函数的技术。每个这样的函数都返回下一个待调用的函数,直到最后一个函数接收完所有参数并返回最终结果。

描述:

已知 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 的调用参数

示例

输入:var fn = function (a, b, c) {return a + b + c}; curryIt(fn)(1)(2)(3);

输出:6

//curryIt 是一个高阶函数,它接收一个函数 fn 作为参数,并返回一个新的函数 fun。
function curryIt(fn) {
   return function fun(a){
//fn.length 返回 fn 函数所声明的参数个数。如果 fn 只有一个参数,那么 curryIt 返回的函数可以直接调用 fn 并传入参数 a
     if(fn.length===1)return fn(a)
        fn=fn.bind(this,a)
        return fun
   }   

}
var fn = function (a, b, c) {return a + b + c}; 
console.log(curryIt(fn)(1)(2)(3))
//curryIt(fn)(1):fn 的参数个数是 3,不等于 1,所以使用 bind 创建一个新函数,这个新函数将 1 作为第一个参数预置给 fn,并返回 fun 函数。
//curryIt(fn)(1)(2):再次调用返回的 fun 函数,这次传入 2。同样,fn 的参数个数仍然不是 1,所以再次使用 bind,这次将 2 作为第二个参数预置给 fn(第一个参数已经是 1 了),并返回 fun 函数。
//curryIt(fn)(1)(2)(3):最后,传入 3。此时,fn 的所有参数都已经满足(因为 fn 需要 3 个参数),所以直接调用 fn(1, 2, 3) 并返回结果 6。
function curryIt(fn) {
    return function a(x1){
        return function b(x2){
            return function c(x3){
                return fn(x1, x2, x3);
            }
        }
    }
}
var fn = function (a, b, c) {return a + b + c}; 
console.log(curryIt(fn)(1)(2)(3))
//curryIt(fn)(1):调用 curryIt 返回的函数 a,并传入 1。返回函数 b,此时 b 的闭包中包含了 x1 = 1。
//curryIt(fn)(1)(2):调用函数 b,并传入 2。返回函数 c,此时 c 的闭包中包含了 x1 = 1 和 x2 = 2。
//curryIt(fn)(1)(2)(3):调用函数 c,并传入 3。此时,所有参数都已经满足,所以直接调用 fn(1, 2, 3) 并返回结果 6。
function curryIt(fn) {
    var length = fn.length,
        args = [];
    var result =  function (arg){
        args.push(arg);
        length --;
        if(length <= 0 ){
            return fn.apply(this, args);
        } else {
            return result;
        }
    }
      
    return result;
}
var fn = function (a, b, c) {return a + b + c}; 
console.log(curryIt(fn)(1)(2)(3))
//curryIt(fn)(1):调用 result 函数,并传入 1。args 变为 [1],length 变为 2。返回 result 函数本身。
//curryIt(fn)(1)(2):再次调用 result 函数,并传入 2。args 变为 [1, 2],length 变为 1。返回 result 函数本身。
//curryIt(fn)(1)(2)(3):再次调用 result 函数,并传入 3。args 变为 [1, 2, 3],length 变为 0。此时,所有参数都已经满足,所以调用 fn.apply(this, [1, 2, 3]),即 fn(1, 2, 3),并返回结果 6。

10、二进制转换

描述:给定二进制字符串,将其换算成对应的十进制数字

示例

输入:'11000000'

输出:192

function base10(str) {
   //parseInt(string, radix)   解析一个字符串并返回指定基数的十进制整数,
   //radix 是2-36之间的整数,表示被解析字符串的基数。
   return parseInt(str,2); //将str看做二进制数,返回十进制数
}
let num = '11000000';
console.log(base10(num))
function base10(str) {
  let arr = str.split("").reverse(); //先将数据进行处理 将个位翻转到第一个去
  let result = 0; 
  for (let i = 0; i < arr.length; i++) {//二进制转十进制,是从个位开始运算再依次与后面相加
      result = result + arr[i] * Math.pow(2, i);  //Math.pow(2, i)代表求2的i次方,在二进制数中,每一位的权重是 2 的幂,从最低位(个位)开始,权重分别为 2 
 } 
  return result;  
}
let num = '11000000';
console.log(base10(num))

11、乘法

描述:求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题

示例

输入:3, 0.0001

输出:0.0003

    function multiply (a, b) {
      var f1 = 1, f2 = 1;
// 如果存在小树点则乘以他的0的个数f1,f2分别存储a,b的倍数最后先算a*b扩大的在除以抵消掉
      if (String(a).indexOf(".") != -1) {
        f1 = String(a).length - (String(a).indexOf(".")+ 1)
        f1 = Math.pow(10, f1)
        a = a * f1
      }
      if (String(b).indexOf(".") != -1) {
        f2 = String(b).length - (String(b).indexOf(".") + 1)
        f2 = Math.pow(10, f2)
        b = b * f2
      }
      return a * b / f1 / f2
    }
let a = 10.097;
let b = 10.102;
console.log(multiply(a, b)); // 输出正确的乘积结果
function multiply(a, b) {
    debugger
    a = a.toString();
    b = b.toString();
    alen = a.indexOf(".") == -1 ? 1 : Math.pow(10, a.length - (a.indexOf(".")+ 1));
    blen = b.indexOf(".") == -1 ? 1 : Math.pow(10, b.length - (b.indexOf(".")+ 1));
    return (a * alen) * (b * blen) / alen / blen
}
let a = 10.097;
let b = 10.102;
console.log(multiply(a, b)); // 输出正确的乘积结果
function multiply(a, b) {
    a = a.toString();
    b = b.toString();
    var aLen = a.substring(a.indexOf(".")+1).length;
    var bLen = a.substring(a.indexOf(".")+1).length;
    return (a * Math.pow(10,aLen)) * (b * Math.pow(10,bLen)) / Math.pow(10,aLen+bLen);
}
let a = 10.097;
let b = 10.102;
console.log(multiply(a, b)); // 输出正确的乘积结果
function multiply(a, b) {
    debugger
    // 计算a和b的小数位数
    let decimalPlacesA = ('' + a).split('.')[1] ? ('' + a).split('.')[1].length : 0;
    let decimalPlacesB = ('' + b).split('.')[1] ? ('' + b).split('.')[1].length : 0;

    // 计算放大倍数
    let factorA = Math.pow(10, decimalPlacesA);
    let factorB = Math.pow(10, decimalPlacesB);

    // 将a和b转换为整数进行乘法运算
    let aInt = a * factorA;
    let bInt = b * factorB;

    // 计算乘积并还原小数位
    let product = (aInt * bInt) / (factorA * factorB);

    return product;
}

let a = 10.097;
let b = 10.102;
console.log(multiply(a, b)); // 输出正确的乘积结果

12、改变上下文

描述:将函数 fn 的执行上下文改为 obj,返回 fn 执行后的值

示例

输入:function() {return this.greeting + ', ' + this.name + '!'; },{name: 'Rebecca', greeting: 'Yo' }

输出:Yo, Rebecca!

function alterContext(fn, obj) {
    return  fn.call(obj)
}
let fn =function() {return this.greeting + ', ' + this.name + '!'; };
let obj ={name: 'Rebecca', greeting: 'Yo' };
console.log(alterContext(fn, obj) );
function alterContext(fn, obj) {
    return  fn.apply(obj)
}
let fn =function() {return this.greeting + ', ' + this.name + '!'; };
let obj ={name: 'Rebecca', greeting: 'Yo' };
console.log(alterContext(fn, obj) );
function alterContext(fn, obj) {
    return  fn.bind(obj)();
}
let fn =function() {return this.greeting + ', ' + this.name + '!'; };
let obj ={name: 'Rebecca', greeting: 'Yo' };
console.log(alterContext(fn, obj) );
function alterContext(fn, obj) {
    obj.fn = fn
    return  obj.fn()
}
let fn =function() {return this.greeting + ', ' + this.name + '!'; };
let obj ={name: 'Rebecca', greeting: 'Yo' };
console.log(alterContext(fn, obj) );

13、批量改变对象的属性

描述:给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。

示例:

输入:var C = function(name) {this.name = name; return this;};

var obj1 = new C('Rebecca');

alterObjects(C, 'What's up');

obj1.greeting;

输出:What's up

function alterObjects(Constructor, greeting) {
    Constructor.prototype.greeting = greeting;
}
var C = function(name) {
    this.name = name; 
    return this;
};
var instance = new C('Rebecca'); 
alterObjects(C, 'What's up'); 
console.log(instance .greeting)

14、判断是否包含数字

描述:给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false

示例:

输入:'abc123'

输出:true

function containsNumber(str) {
debugger   
    for(let i= 0; i< str.length; i++) {
        if(!isNaN(Number(str[i]))) return true
    }
    return false
}
let str ="abc123";
console.log(containsNumber(str))
function containsNumber(str) {
    const reg = /([0-9])/
    return reg.test(str)
}
let str ="abc123";
console.log(containsNumber(str))

15、判断是否以元音字母结尾

描述:

给定字符串 str,检查其是否以元音字母结尾
1、元音字母包括 a,e,i,o,u,以及对应的大写
2、包含返回 true,否则返回 false

示例

输入:'gorilla'

输出:true

function endsWithVowel(str) {
            debugger
            let arr = 'aeiou';
            let end = str[str.length-1];
            return arr.indexOf(end)>-1||arr.toUpperCase().indexOf(end)>-1?true:false;
}
let str = 'gorillO';
console.log(endsWithVowel(str));
function endsWithVowel(str) {
          let reg = /[aeiou]$/i;// $表示以什么结尾, i表示不区分大小写搜索
    return   reg.test(str);
}
let str = 'gorilla';
console.log(endsWithVowel(str));

二、简单

1、获取字符串的长度

描述:如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1,否则如果字符 Unicode 编码 > 255 则长度为 2(它的意思是如果传进来的参数(也就是bUnicode255For1)是传的true,那么字符串中每个字符按照1的长度来计算;如果传进来的是flase,那么再对每一个字符进行判断,如果它们的unicode编码>255(a=97),那么该字符就按照2的长度来计算,否则长度为1)

示例:

输入:'hello world, 牛客', false

输出:17

function strLength(s, bUnicode255For1) {
    let len = s.length
    if(!bUnicode255For1){
        for(let i in s){
            if(s.charCodeAt(i)>255)len++
        }       
    }
    return len
}
let s="hello world, 牛客";
console.log(strLength(s, false));
function strLength(s, bUnicode255For1) {
    if (bUnicode255For1) {
        return s.length;
    } else {
        for (var i = 0, length = 0; i < s.length; i++) {
            if (s.charCodeAt(i) > 255) {
                length = length + 2;
            } else {
                length++;
            }
        }
        return length;
    }
}
let s="hello world, 牛客";
console.log(strLength(s, false));

2、 返回函数

描述:

实现函数 functionFunction,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', '
3、所有函数的参数数量为 1,且均为 String 类型

示例

输入:functionFunction('Hello')('world')

输出:Hello, world

function functionFunction(str1) {
    return function(str2){
        return str1+", "+str2
    }
}
functionFunction("hello")("world");
function functionFunction(str) {
    let f = function(s) {
        return str + ', ' + s
    }
    return f
}
functionFunction("hello")("world");
function functionFunction(str) {
    debugger
    let args = [].slice.call(arguments)
    return function() {
        args = args.concat([].slice.call(arguments))
        return args.join(', ')
    }
}
functionFunction("hello")("world");

3、使用 apply 调用函数

描述:

实现函数 callIt,调用之后满足如下条件
1、返回的结果为调用 fn 之后的结果
2、fn 的调用参数为 callIt 的第一个参数之后的全部参数

function callIt(fn, ...args) {
    return fn.apply(null, args);
}
function add(a, b) {
    return a + b;
}
console.log(callIt(add, 5, 3)); // 输出: 8
function callIt(fn) {
 return fn.apply(this,[].slice.call(arguments,1))
}
function add(a, b) {
    return a + b;
}
console.log(callIt(add, 5, 3)); // 输出: 8
function callIt(fn) {
  var arr=[];
  for(var i=1;i<arguments.length;i++){
    arr.push(arguments[i])
  }
  return fn.apply(callIt,arr)
}
function add(a, b) {
    return a + b;
}
console.log(callIt(add, 5, 3)); // 输出: 8

4、二次封装函数

描述:

实现函数 partialUsingArguments,调用之后满足如下条件:
1、返回一个函数 result
2、调用 result 之后,返回的结果与调用函数 fn 的结果一致
3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数

function partialUsingArguments(fn, ...initialArgs) {
    debugger
    return function(...laterArgs) {
        const allArgs = initialArgs.concat(laterArgs);
        return fn.apply(this, allArgs);
    };
}

function sum(a, b, c) {
    return a + b + c;
}
console.log(partialUsingArguments(sum, 1, 2)(3)); // 输出: 6
function partialUsingArguments(fn) {
    let args1 = Array.prototype.slice.call(arguments, 1)

    return function() {
        let args2 = Array.prototype.slice.call(arguments, 0)
        return fn.apply(this, args1.concat(args2))
    }
}

function sum(a, b, c,d) {
    return a + b + c+d;
}
console.log(partialUsingArguments(sum, 1, 2)(3,4)); // 输出:10
function partialUsingArguments(fn) {
    var arr = [].slice.call(arguments, 1);
    return result = function(){
        return fn.apply(this, arr.concat([].slice.call(arguments)) );
    };
}

function sum(a, b, c,d) {
    return a + b + c+d;
}
console.log(partialUsingArguments(sum, 1, 2)(3,4)); // 输出: 10

5、二进制转换

描述:

获取数字 num 二进制形式第 bit 位的值。注意:
1、bit 从 1 开始
2、返回 0 或 1
3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1

示例

输入:128, 8

输出:1

function valueAtBit(num, bit) {
    debugger
     if(bit < 1) return
     var newN = num.toString(2)
    return Number(newN.slice(newN.length-bit,newN.length-bit+1))
}

let num = 128
console.log(valueAtBit(num, 2));
function valueAtBit(num, bit) {
    if(bit < 1) return
    var numberString = num.toString(2).split("").reverse().join("") 
    //十进制转二进制-》数组-》反转-》字符串
    return numberString[bit-1]
}
let num = 128
console.log(valueAtBit(num, 2));
function valueAtBit(num, bit) {
    let str = num.toString(2);
    return str.substr(-bit,1);
}
let num = 128
console.log(valueAtBit(num, 2));

6、二进制转换

描述:

将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。

示例

输入:65

输出:01000001

function convertToBinary(num) {
    let str = num.toString(2); // 将数字转换为二进制字符串
    let len = 8 - str.length;  // 计算需要补0的个数

    // 使用for循环补0
    for (let i = 0; i < len; i++) {
        str = "0" + str;
    }
    return str;
}

let num = 65;
console.log(convertToBinary(num)); // 输出:01000001
function convertToBinary(num) {
    return ('0'.repeat(8) + num.toString(2)).slice(-8);//从字符串末位向前截取8位
}

let num = 65;
console.log(convertToBinary(num)); // 输出:01000001
function convertToBinary(num) {
    let str = num.toString(2); 
    let len = 8 - str.length;  

   return ('0'.repeat(len) + num.toString(2));
}

let num = 65;
console.log(convertToBinary(num));
function convertToBinary(num) {
    let res=num.toString(2);
   return res.length<8?new Array(8-res.length).fill(0).join('')+res:res;
  //创建一个用0填充的数组变成字符串后与res拼接
}
let num = 65;
console.log(convertToBinary(num)); // 输出:01000001
function convertToBinary(num) {
var s = num.toString(2);
    while(s.length<8){
        s = "0"+s;
    }
    return s;
}
let num = 65;
console.log(convertToBinary(num)); // 输出:01000001

7、属性遍历

描述:

找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)
1、返回数组,格式为 key: value
2、结果数组不要求顺序

示例

输入:var C = function() {this.foo = 'bar'; this.baz = 'bim';};

C.prototype.bop = 'bip';

iterate(new C());

输出:["foo: bar", "baz: bim"]

function iterate(obj) {
    const result = [];
    for (let key in obj) {//for in可以遍历到obj的原型属性和方法
        // 使用 hasOwnProperty 检查属性是否是对象自身的属性,而不是从原型链继承的
        if (obj.hasOwnProperty(key)) {
            result.push(`${key}: ${obj[key]}`);
        }
    }
    return result;
}
var C = function() {
    this.foo = 'bar'; 
    this.baz = 'bim';
};
C.prototype.bop = 'bip';
console.log(iterate(new C()));  // 输出: ["foo: bar", "baz: bim"]
function iterate(obj) {
    const keyArr = Object.keys(obj);
  //Object.keys(obj) 只会遍历实例属性key值,不会遍历原型上的属性
    const temp = []
    for(let i in keyArr){
        temp[i] = keyArr[i].concat(': ',obj[keyArr[i]])
    }
    return temp
}
var C = function() {
    this.foo = 'bar'; 
    this.baz = 'bim';
};
C.prototype.bop = 'bip';
console.log(iterate(new C()));  // 输出: ["foo: bar", "baz: bim"]
function iterate(obj) {
   return Object.keys(obj).map( k => `${k}: ${obj[k]}`)
}
var C = function() {
    this.foo = 'bar'; 
    this.baz = 'bim';
};
C.prototype.bop = 'bip';
console.log(iterate(new C()));  // 输出: ["foo: bar", "baz: bim"]

8、 检查重复字符串

描述:给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false

示例

输入:'rattler'

输出:true

function containsRepeatingLetter(str) {
    for(let i=0;i<str.length-1;i++){//判断相邻字符是否相等,再判断是否为字母
        if(str.charAt(i)==str.charAt(i+1)&& ((str.charAt(i)>='a'&&str.charAt(i)<='z')||(str.charAt(i)>='A'&&str.charAt(i)<='Z'))){
            return true;
        }
    }
    return false;
}
let str= 'rattler';
console.log(containsRepeatingLetter(str) );
function containsRepeatingLetter(str) {
    return /([a-zA-Z])\1/.test(str)
}
let str= 'rarRRler';
console.log(containsRepeatingLetter(str) );

9、获取指定字符串

描述:

给定字符串 str,检查其是否包含 连续3个数字,请使用正则表达式实现。
1、如果包含,返回最先出现的 3 个数字的字符串
2、如果不包含,返回 false

示例

输入:'9876543'

输出:987

function captureThreeNumbers(str) {
    debugger
    var result = str.match(/(\d{3})/)
    return result ? result[0] : false
}
let input = '987657777777743';
console.log(captureThreeNumbers(input)); // 输出: 987

10、 判断是否符合指定格式

描述:

给定字符串 str,检查其是否符合如下格式
1、XXX-XXX-XXXX
2、其中 X 为 Number 类型

示例

输入:'800-555-1212'

输出:true

function matchesPattern(str) {
            let regs = /^\d{3}-\d{3}-\d{4}$/
            return regs.test(str)
}
let str ='800-555-1212';
matchesPattern(str);
 function matchesPattern(str) {
           return (/^\d\d\d-\d\d\d-\d\d\d\d$/.test(str));
}
let str ='800-555-1212';
matchesPattern(str) ;
function matchesPattern(str) {
var reg=/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/;
    return reg.test(str);
}
let str ='800-555-1212'
matchesPattern(str) 

三、中等

1、列表内容排序再渲染

描述:

场景描述:在一个 HTML 页面中,有一个无序列表(ul),其中包含了一些项目(li)。每个项目都有一个文本内容和一个唯一的 ID。你需要编写一个 JavaScript 函数来提取列表中所有项目的文本内容,并将它们按照 ID 进行排序,然后将排序后的文本内容重新渲染回去。

示例:

输入:

输出:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <ul id="myList">
    <li id="item1">项目 1</li>
    <li id="item3">项目 3</li>
    <li id="item2">项目 2</li>
    <li id="item4">项目 4</li>
  </ul>
  <script>
     function sortAndReturnTextContent() {
	 debugger
        const items = document.getElementById('myList').children
        // 在此补全代码
        document.getElementById('myList').innerHTML = Array.from(items)
          .sort((a, b) => parseInt(a.id.slice(4)) - parseInt(b.id.slice(4)))
          .map((item) => item.outerHTML)
          .join('')
      }
      sortAndReturnTextContent()
  </script>

</body>

</html>
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">


</head>

<body>
  <ul id="myList">
    <li id="item1">项目 1</li>
    <li id="item3">项目 3</li>
    <li id="item2">项目 2</li>
    <li id="item4">项目 4</li>
  </ul>
  <script>
     function sortAndReturnTextContent() {
	 debugger
      const items = document.getElementById('myList').children;
      const liArrays = [...items];
        liArrays.sort((a, b) => {
          return parseInt(a.id.slice(4)) - parseInt(b.id.slice(4));
        });
        for (let i of liArrays) {
          document.getElementById("myList").appendChild(i);
          //如果要附加的节点已经是某个元素的一个子节点,.appendChild()会先将该节点从其当前位置移除,然后再将其附加到指定元素的子节点列表的末尾。
        }
    }
      sortAndReturnTextContent()
  </script>

</body>

</html>

2、直角三角形

描述:

请补全JavaScript代码,要求在页面上渲染出一个直角三角形,三角形换行要求使用"br"实现。三角形如下:
*
**


<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div class='triangle'></div>

        <script>
            var triangle = document.querySelector('.triangle');
            // 补全代码
            let str = "";
            for(let i=0;i<3;i++){
              for(let j=0;j<i+1;j++){
                str+="*";
             }
               str+="</br>";
            }
            triangle.innerHTML=str;
            
        </script>
    </body>
</html>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div class='triangle'>
            *<br>**<br>***<br>
        </div>

        <script>
            var triangle = document.querySelector('.triangle');
            // 补全代码
            var str='';
            for(var i=1;i<=3;i++){
                str+=`${'*'.repeat(i)}<br>`;
            }
            triangle.innerHTML=str;
        </script>
    </body>
</html>

3、文件扩展名

描述:请补全JavaScript代码,要求以字符串的形式返回文件名扩展名,文件名参数为"filename"。

const _getExFilename = (filename) => {
     return "."+filename.split(".")[ filename.split(".").length-1]
}
console.log(_getExFilename("port.xml"))
const _getExFilename = (filename) => {
  // 1.获取最后一个.的索引值
  let index = filename.lastIndexOf(".");
  // 2.截取.及其后面的内容
  return filename.slice(0,index) && index !== -1 ? filename.slice(index) : '';
}
console.log(_getExFilename("port.xml"))
const _getExFilename = (filename) => {
  let f = filename.indexOf('.')
  return filename.slice(f,filename.length)
}
 console.log(_getExFilename("port.xml"))

4、分隔符

描述:请补全JavaScript代码,要求返回参数数字的千分位分隔符字符串。

示例:

输入:_comma(12300)

输出:'12,300'

function _comma(number) {
  let res = ''
  let count = 0
  const negative = number < 0 ? '-' : ''
  number = Math.abs(number).toString()
  for (let i = number.length - 1; i >= 0; i--) {
    count += 1
    res = number[i] + res
    if (count % 3 === 0 && i !== 0 && number[i] !== '.') {
      res = ',' + res
    }
  }
  return negative + res
}
 
console.log(_comma(-123456789.89)) // -123,456,789.89
function _comma(number) {
    let isnegative = number < 0;
    number = Math.abs(number);
    let numberStr = number.toString();
    let result = numberStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return isnegative ? "-" + result : result;
}
console.log(_comma(-123456789.89)) // -123,456,789.89
function _comma(number) {
    debugger
    // 补全代码
    let isnegative = (number < 0)
    console.log(isnegative);
    number = Math.abs(number);
    let numberStr = String(number);
    let arr = numberStr.split("");
    let length = arr.length;
    let round = Math.floor(length / 3);
    if (length % 3 === 0) round--;
    while (round > 0) {
        arr.splice((round) * (-3), 0, ",");
        round--;
    }
    let result = arr.join("");
    if (isnegative) result = '-' + result;
    return (result);
}
console.log(_comma(-123456789.89)) // -123,456,789.89

5、单向绑定

描述:

请补全JavaScript代码,要求每当id为"input"的输入框值发生改变时触发id为"span"的标签内容同步改变。
注意:

  1. 必须使用DOM0级标准事件(onchange)
<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8>
    </head>
    <body>
    	<input id="input" type="text" onchange="change(value)"/>
        <span id="span"></span>

        <script type="text/javascript">
            // 补全代码
                let content=document.querySelector("#span")
              function change(val){
                content.innerHTML=val
            }
        </script>
    </body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8>
    </head>
    <body>
    	<input id="input" type="text" />
        <span id="span"></span>

        <script type="text/javascript">
            document.getElementById("input").onchange = function(){
                // dom事件里的函数的this指向触发者,即input标签
                document.getElementById("span").innerHTML = this.value
            }
        </script>
    </body>
</html>

6、创建数组

描述:

请补全JavaScript代码,要求返回一个长度为参数值并且每一项值都为参数值的数组。
注意:

  1. 请勿直接使用for/while
const _createArray = (number) => {
    return Array(number).fill(number)
}
console.log(_createArray(4));
const _createArray = (number) => {
    return Array.from({length: number}, () => number);
  //Array.from函数接收两个参数,第一个参数为数组或对象,都表示返回数组的长度。当参数为数组时它确定了返回的新数组长度,当参数为对象时,需要添加“length”属性表明数组长度
//第二个参数为一个函数,即第一个数组参数中的每一项都调用该函数
}
console.log(_createArray(10));
const _createArray = (number) => {
      const array = [...Array(number)].map((item)=>{
          return number
      })      
      return array
}
console.log(_createArray(4));
const _createArray = (number) => {
      const list = new Array();
      let newNumer = number
      const fn = (list,newNumer) => {
          if(newNumer > 0){
              list.push(number);
              newNumber = newNumer - 1 ;
              fn(list,newNumber)
          }
      }
      fn(list,newNumer)
      return list
}
console.log(_createArray(4));

7、判断版本

描述:

请补全JavaScript代码,该函数接收两个参数分别为旧版本、新版本,当新版本高于旧版本时表明需要更新,返回true,否则返回false。
注意:

  1. 版本号格式均为"X.X.X"
  2. X属于[0,9]
  3. 当两个版本号相同时,不需要更新
const _shouldUpdate = (oldVersion, newVersion) => {
    let oldversion = parseInt(oldVersion.split('.').join(''))
    let newversion = parseInt(newVersion.split('.').join(''))
    return newversion > oldversion
}
console.log( _shouldUpdate("1.4.1","1.4.9"))
const _shouldUpdate = (oldVersion, newVersion) => {
   return oldVersion < newVersion;
  //三个X都是1位数[0,9],可以直接比较字符串大小
}
console.log( _shouldUpdate("1.4.9","1.5.1"))

8、无重复数组

描述:

请补全JavaScript代码,实现一个函数,要求如下:

  1. 根据输入的数字范围[start,end]和随机数个数"n"生成随机数
  2. 生成的随机数存储到数组中,返回该数组
  3. 返回的数组不能有相同元素
    注意:
  4. 不需要考虑"n"大于数字范围的情况

示例

输入:getUniqueNums(2,10,4)

输出:[4,6,2,8]

const _getUniqueNums = (start,end,n) => {
    let set = new Set()
    while(set.size < n) {
        set.add(Math.floor(Math.random() * (end - start + 1)+ start ))
    }
    return [...set]
}
console.log(_getUniqueNums(2,10,6))
const _getUniqueNums = (start,end,n) => {
    var arr1 = []
    var randomArr = []
    for(var i = start ;i<=end;i++){
        arr1.push(i)              
    }
    debugger
    while(randomArr.length<n){
        var randomIndex = Math.floor(Math.random()*arr1.length)
        randomArr.push(arr1[randomIndex])
        arr1.splice(randomIndex,1)
    }
    return randomArr
}
console.log(_getUniqueNums(2,10,6))

9、数组排序

描述

请补全JavaScript代码,根据预设代码中的数组,实现以下功能:

  1. 列表只展示数组中的name属性
  2. 实现点击"销量升序"按钮,列表内容按照销量升序重新渲染
  3. 实现点击"销量降序"按钮,列表内容按照销量降序重新渲染
    注意:
  4. 必须使用DOM0级标准事件(onclick)
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <button class='up'>销量升序</button>
        <button class='down'>销量降序</button>
        <ul></ul>

        <script>
            var cups = [
                { type: 1, price: 100, color: 'black', sales: 3000, name: '牛客logo马克杯' },
                { type: 2, price: 40, color: 'blue', sales: 1000, name: '无盖星空杯' },
                { type: 4, price: 60, color: 'green', sales: 200, name: '老式茶杯' },
                { type: 3, price: 50, color: 'green', sales: 600, name: '欧式印花杯' }
            ];
            var ul = document.querySelector('ul');
            var upbtn = document.querySelector('.up');
            var downbtn = document.querySelector('.down');

            // 渲染列表的函数
            function renderList(cupsArray) {
                ul.innerHTML = ''; 
                cupsArray.forEach(cup => {
                    var li = document.createElement('li');
                    li.textContent = cup.name;
                    ul.appendChild(li);
                });
            }

            // 升序排序函数
            function sortAsc(cupsArray) {
                return cupsArray.sort((a, b) => a.sales - b.sales);
            }

            // 降序排序函数
            function sortDesc(cupsArray) {
                return cupsArray.sort((a, b) => b.sales - a.sales);
            }

            // 绑定点击事件
            upbtn.onclick = function() {
                renderList(sortAsc([...cups])); // 使用解构赋值来避免直接修改原数组
            };

            downbtn.onclick = function() {
                renderList(sortDesc([...cups])); 
            };
            renderList(cups);
        </script>
    </body>
</html>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <button class='up'>销量升序</button>
        <button class='down'>销量降序</button>
        <ul></ul>

        <script>
            var cups = [
                { type: 1, price: 100, color: 'black', sales: 3000, name: '牛客logo马克杯' },
                { type: 2, price: 40, color: 'blue', sales: 1000, name: '无盖星空杯' },
                { type: 4, price: 60, color: 'green', sales: 200, name: '老式茶杯' },
                { type: 3, price: 50, color: 'green', sales: 600, name: '欧式印花杯' }
            ]
            var ul = document.querySelector('ul');
            var upbtn = document.querySelector('.up');
            var downbtn = document.querySelector('.down');
            // 补全代码
            upbtn.onclick = function(){
                let newCups = [...cups];
                newCups.sort((x,y)=>{
                  return x.sales-y.sales
                });
               rendList(newCups);
            }
             downbtn.onclick = function(){
                let newCups = [...cups];
                newCups.sort((x,y)=>{
                  return y.sales-x.sales
                })
				rendList(newCups);
              
            }
			function rendList(newCups){
			    let str ="";
                newCups.map((x,y)=>{
                  str = str +"<li>"+x.name+"</li>";
                })
                ul.innerHTML = str;
			}
            
        </script>
    </body>
</html>

10、新数组

描述:请补全JavaScript代码,该函数接受两个参数分别为数组、索引值,要求在不改变原数组的情况下返回删除了索引项的新数组。

const _delete = (array,index) => {
    let newarray = array.concat()
    newarray.splice(index,1);
    return newarray;
}
console.log(_delete([1,2,4,6],2));
const _delete = (array,index) => {
  let arrayNew = [...array];
  arrayNew.splice(index,1);
   return arrayNew;        
}
console.log(_delete([1,2,4,6],2));
const _delete = (array,index) => {
    return array.filter((n,i) => i!=index)
}
 console.log(_delete([1,2,4,6],2))
const _delete = (array,index) => {
   return array.slice(0,index).concat(array.slice(index+1))
}
console.log(_delete([1,2,4,6],2))

11、计数器

描述:

请补全JavaScript代码,要求每次调用函数"closure"时会返回一个新计数器。每当调用某个计数器时会返回一个数字且该数字会累加1。
注意:

  1. 初次调用返回值为1
  2. 每个计数器所统计的数字是独立的
function closure() {
    // 存储计数器的值
    let count = 0;

    // 返回一个函数,该函数将作为计数器
    return function() {    
        count += 1;
        return count;
    };
}

// 测试代码
let counter1 = closure(); // 创建一个新的计数器
let counter2 = closure(); // 创建另一个新的计数器

console.log(counter1()); // 输出: 1,初次调用返回值为1
console.log(counter1()); // 输出: 2,计数器1的值累加1
console.log(counter2()); // 输出: 1,初次调用返回值为1(与counter1独立)
console.log(counter1()); // 输出: 3,计数器1的值继续累加1
console.log(counter2()); // 输出: 2,计数器2的值累加1

12、列表动态渲染

描述:

请补全JavaScript代码,将预设代码中的"people"数组渲染在页面中。实现下面的列表:

  • 牛油1号 20岁
  • 牛油2号 21岁
  • 牛油3号 19岁
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <ul></ul>
        <script>
            var people = [
                { name: '牛油1号', id: 1, age: 20 },
                { name: '牛油2号', id: 2, age: 21 },
                { name: '牛油3号', id: 3, age: 19 },
            ]
            var ul = document.querySelector('ul');
            // 补全代码
            let str = "";
            people.map(x=>{
                str += `<li>${x.name}&nbsp;${x.age}</li>`
            })
            ul.innerHTML = str
        </script>
    </body>
</html>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <ul></ul>

        <script>
            var people = [
                { name: '牛油1号', id: 1, age: 20 },
                { name: '牛油2号', id: 2, age: 21 },
                { name: '牛油3号', id: 3, age: 19 },
            ]
            var ul = document.querySelector('ul');
            // 补全代码
            let str = "";
			for (const item of people) {
			str += `<li>${item.name}&nbsp;${item.age}</li>`
           }
            ul.innerHTML = str;
        </script>
    </body>
</html>

13、模板字符串

描述:

请补全JavaScript代码,实现以下功能:

  1. 根据已有的person对象的注册时间求出距离当前时间的天数(天数向下取整)。
  2. 将获得的天数和person数据拼接成字符串,作为h2标签的内容。
    注意:使用模板字符串进行字符串拼接,字符串最终内容如:尊贵的牛客网2级用户小丽您好,您已经注册牛客网3天啦~
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <h2></h2>

    <script>
        var person = {
            level: '2',
            name: '小丽',
            registTime: '2021-11-01',
        }
        var h2 = document.querySelector('h2');
        // 补全代码
        let str = "";
        // 输入日期字符串
        const inputDateString =person.registTime;
        const inputDate = new Date(inputDateString);
        const currentDate = new Date();
        const timeDifference = currentDate - inputDate;
        const daysDifference = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
         h2.innerHTML = `尊贵的牛客网${person.level}级用户小丽您好,您已经注册牛客网${daysDifference}天啦~`
            
        </script>
    </body>
</html>

14、类继承

描述:

请补全JavaScript代码,完成类的继承。要求如下:

  1. "Chinese"类继承于"Human"类
  2. "Human"类实现一个函数"getName",返回该实例的"name"属性
  3. "Chinese"类构造函数有两个参数,分别为"name"、"age"
  4. "Chinese"类实现一个函数"getAge",返回该实例的"age"属性
class Human {
    constructor(name) {
        this.name = name;
        this.kingdom = 'animal';
        this.color = ['yellow', 'white', 'brown', 'black'];
    }

    // 实现 getName 方法,返回实例的 name 属性
    getName() {
        return this.name;
    }
}

// Chinese 类继承自 Human 类
class Chinese extends Human {
    constructor(name, age) {
        // 调用父类的构造函数,传入 name 参数
        super(name);
        this.age = age;
    }

    // 实现 getAge 方法,返回实例的 age 属性
    getAge() {
        return this.age;
    }
}

// 示例用法
const chinesePerson = new Chinese('张三', 30);
console.log(chinesePerson.getName()); // 输出: 张三
console.log(chinesePerson.getAge());  // 输出: 30

15、参数解析器

描述:

请补全JavaScript代码,要求将字符串参数URL中的参数解析并以对象的形式返回。

示例

输入:getParams('nowcoder.com/online?id=1…')

输出:{id:1, salas: 100}

function _getParams(url) {
          let splitUrl = url.slice(url.lastIndexOf('?')+1).split('&')
          let obj = {}
          splitUrl.map(n => {
              let [key,value] = n.split('=')
              obj[key] = value
          })
          console.log(obj)
          return obj
      }
getParams('https://nowcoder.com/online?id=1&salas=1000')
function _getParams(url) {
    var searchString = url.substring(url.indexOf('?'));//截取字符串
    const params = new URLSearchParams(searchString);//通过URLSearchParams方法变成深度数组
    const obj = Object.fromEntries(params)//通过fromEntries转变成对象
    console.log(obj)
    return obj
}
getParams('https://nowcoder.com/online?id=1&salas=1000')
const getParams = (url) => {
  let arr = url.match(/(\w+)=(\w+)/gi);//匹配 (\w+)=(\w+) 的子字符串
  let obj = {};
  arr.map(item => {
  	let [key, value] = item.split("=");
      obj[key] = value;
  })
  return obj;

 }
getParams('https://nowcoder.com/online?id=1&salas=1000')
  const getParams = (url) => {
    let params= url.split("?")[1].split("&");
    let obj = {};
    params.map(x=>{
        let param = x.split("=");
        obj[param[0]]=param[1];
    })
    return obj;
}
getParams('https://nowcoder.com/online?id=1&salas=1000')

16、生成页码

描述:

请补全JavaScript代码,要求根据参数动态生成"li"标签页码并插入"ul"标签下。要求如下:

  1. "allItem"为总数据项个数,"pageItem"为每页的数据项个数
  2. "li"标签内容为当前页码数,页码从1开始

示例

输入:_createPage(13,2)

输出:"li"长度为7,"li"内容依次为"1","2","3","4","5","6","7"

<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8>
    </head>
    <body>
    	<ul id="ul">
            
        </ul>
        <script type="text/javascript">
            const _createPage = (allItem, pageItem) => {
			debugger
               let page = Math.ceil(allItem/pageItem);//向上取整
               let str = "";
               for (let i=1;i<=page;i++){
                str += `<li>${i}</li>`;
               }
               document.getElementById("id").innerHTML = str;
            }
            console.log(_createPage(13,2));
        </script>
    </body>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8>
</head>
<body>
  <ul id="ul">
      
  </ul>
  <script type="text/javascript">
    const _createPage = (allItem, pageItem) => {
      let ul = document.querySelector('#ul')
      let pageNumber = Math.ceil(allItem / pageItem)
      for(let i=1 ; i<=pageNumber ; i++) {
          let li = document.createElement('li')
          li.innerText = i
          ul.appendChild(li)
      }
    }
     console.log(_createPage(13,2));
        </script>
    </body>
</html>

17、总成绩排名

描述:请补全JavaScript代码,要求将数组参数中的对象以总成绩(包括性"chinese"、"math"、"english")从高到低进行排序并返回。

 let arr =[
            {id:"001",chinese:112,math:139,english:103},
            {id:"002",chinese:132,math:129,english:113},
            {id:"003",chinese:122,math:119,english:123},
            {id:"004",chinese:102,math:109,english:133}
            ]
        const _rank = array => {
            // 补全代码
            array.map(x=>{
                return x.total = x.chinese+x.math+x.english;
            })
            array.sort((a,b)=>{
                return b.total-a.total
            })
             return array
        }
        console.log( _rank(arr));
  let arr =[            {id:"001",chinese:112,math:139,english:103},            {id:"002",chinese:132,math:129,english:113},            {id:"003",chinese:122,math:119,english:123},            {id:"004",chinese:102,math:109,english:133}            ]
 const _rank = array => {         
      return array.sort((a,b)=>(b.chinese+b.math+b.english) - (a.chinese+a.math+a.english))
}
console.log( _rank(arr));

18、子字符串频次

描述:请补全JavaScript代码,该函数接受两个参数分别为字符串、子字符串,要求返回子字符串在字符串中出现的频次。

const _searchStrIndexOf = (str, target) => {
	return str.split(target).length - 1
}
console.log( _searchStrIndexOf("3rekoreuurere44uu444","uu"));
const _searchStrIndexOf = (str, target) => {
	let reg=new RegExp(target,'g');
	return str.match(reg).length;
  //使用正则表达来计算共有几个target,match会返回符合条件的数组
}
console.log( _searchStrIndexOf("3rekoreuurere44uu444","uu"));
const _searchStrIndexOf = (str, target) => {
	let index = str.indexOf(target)
	let sum = 0
	while (index > -1) {
      //在每次循环中,上一个找到的位置的下一个字符开始搜索
		index = str.indexOf(target, index + 1);
		sum++
		}
	return sum
}
console.log( _searchStrIndexOf("3rekoreuurere44uu444","uu"));
const _searchStrIndexOf = (str, target) => {
    let n = target.length;
    let l = str.length;
    let result = 0, i = 0;
    debugger
    while (i < l - n) { // 修改循环条件
        let tmp = str.substr(i, n);
        if (tmp === target) {
            result++;
        }
        i++;
    }
    return result;
}
    console.log( _searchStrIndexOf("3rekoreuurere44uu444","uu"));

19、继承

描述:

请补全JavaScript代码,实现以下功能:

  1. 给"Human"构造函数的原型对象添加"getName"方法,返回当前实例"name"属性
  2. 将"Chinese"构造函数继承于"Human"构造函数
  3. 给"Chinese"构造函数的原型对象添加"getAge"方法,返回当前实例"age"属性
 function Human(name) {
                this.name = name
                this.kingdom = 'animal'
                this.color = ['yellow', 'white', 'brown', 'black']
            }

          //补全的位置开始:
            Human.prototype.getName = function(){
                return this.name;
            };
        //补全的位置结束

            function Chinese(name,age) {
                Human.call(this,name)
                this.age = age
                this.color = 'yellow'
            }

        //补全的位置开始:
            Chinese.prototype = new Human();
            Chinese.prototype.constructor = Chinese;
            Chinese.prototype.getAge = function(){
                return this.age;
            }
       //补全的位置结束

20、判断斐波那契数组

描述:

请补全JavaScript代码,要求以Boolean的形式返回参数数组是否为斐波那契数列。在数学上,斐波那契数列以如下方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N)
注意:

  1. [0,1,1]为最短有效斐波那契数列
 const _isFibonacci = array => {
                if(array.length<3){
                    return false;
                }
                let flag = true;
                for(let i=array.lenng-1;i>=2;i--){
                    if(!(array[i]= array[i-1]+array[i-2])){
                        flag = false;
                        return false
                    }

                }
                return flag
                
            }
            console.log(_isFibonacci([0,1,1,2,3,5]))
const _isFibonacci = array => {
    if(array.length < 3 || array[0] !== 0 || array[1] !== 1) return false
    for(let i=2 ; i<array.length ; i++) {
        if(array[i] === array[i-1] + array[i-2]) continue
        return false
    }
    return true
}
console.log(_isFibonacci([0,1,1,2,3,5]))
const _isFibonacci = (array) => {
    // 判断长度是否合格
    if (array.length < 3) return false;
    // 当index索引值小于3时判断是否为最短且有效的斐波那契数列
    // 当index索引值大于3时判断当前item值是否为前两项索引item项值的和
    return array.every((item, index) =>
      index < 3
        ? array[0] === 0 && array[1] === 1 && array[2] === 1
        : item === array[index - 1] + array[index - 2]
    );
};
console.log(_isFibonacci([0,1,1,2,3,5]))