牛客网练习题

牛客网JavaScript基础练习挑战记录

数据类型

FED20 基本数据类型检测

image-20211228152644970

function _typeof(value) {
  return typeof value;
}

FED22 数据类型转换

image-20211228161202765

// ES6模板字符串语法
function _splice(left, right) {
  return `${left}${right}`;
}

// 简单的字符串拼接
function _splice(left, right) {
  return left.toString() + right.toString();
}

运算符

FED23 阶乘

image-20211228164633698

function _factorial(number) {
  let res = 1;
  for (let i = 1; i <= number; i++) {
    res *= i;
  }
  return res;
}

FED24 绝对值

image-20211228164938801

``` js // 判断数字大小,进行返回 function _abs(number) { return number >= 0 ? number : -number; } // Math.abs() function _abs(number) { return Math.abs(number) } ```

FED25 幂

image-20211228171039916

// 简单函数写法
function _pow(number, power) {
  let res = 1;
  while (power > 0) {
    res *= number;
    power--;
  }
  return res;
}

// 直接调用库
function _pow(number, power) {
  return number ** power;
}

FED26 平方根

image-20211228171333460

function _sqrt(number) {
  return Math.sqrt(number);
}

FED27 余数

image-20211228171456725

function _remainder(value) {
  return value % 2;
}

FED56 数组求和

image-20211228172230608

// 遍历数组累加
function sum(arr) {
  let sum = 0;
  arr.forEach((item) => (sum += item));
  return sum;
}

// ES6中的reduce()求和
function sum(arr) {
  return arr.reduce((acc, cur) => acc + cur);
}

FED69 完全等同

image-20210726143657770

function identity(val1, val2) {
  return val1 === val2;
}

//知识点: == 弱相等,不同类型的数据相比较的话,会进行自动数据类型转换,
//       === 严格相等,比较时不会做任何数据类型转换,值要相同,数据类型也要相同

FED70 或运算

image-20210815124741282

function or(a, b) {
  return a || b;
}

FED71 且运算

image-20210815124857068

function add(a, b) {
  return a && b;
}
//且运算规则:如果a的布尔值是true ===> 返回b的值
//				 如果a的布尔值是false===> 直接返回a的值,且不再对第二个运算子求值

FED72 字符串字符统计

image-20211228225233380

function count(str) {
  let obj = {};
  let arr = [...str].filter((i) => i !== " "); // 字符串打散成数组并过滤掉空格
  for (let item of arr) {
    // 遍历数组
    item in obj ? obj[item]++ : (obj[item] = 1); // 如果空对象中已经有属性,计数加一;没有属性添加这个属性值为一
  }
  return obj;
}

流程控制

FED28 返回星期数

image-20211228221947130

function _getday(value) {
  switch (value) {
    case 1:
      return "星期一";
    case 2:
      return "星期二";
    case 3:
      return "星期三";
    case 4:
      return "星期四";
    case 5:
      return "星期五";
    case 6:
      return "星期六";
    case 7:
      return "星期天";
  }
}

内置对象

FED29 从大到小排序

image-20211228181454502

// 直接使用内置的排序函数
function _sort(array) {
  return array.sort((a, b) => b - a);
}

FED30 大写字符串

image-20211228181617459

function _touppercase(string) {
  return string.toUpperCase();
}

FED31 对象属性键名

image-20211228182212451

// 使用for...in... 遍历对象的键,数组也是一种对象
function _keys(object) {
  let arr = [];
  for (let key in object) {
    arr.push(key);
  }
  return arr;
}

FED32 对象数字

image-20211228182937433

function _numbertoobject(number) {
  return { number };
}

FED33 对象字符串

image-20211228183114822

function _stringtoobject(string) {
  return { string };
}

FED34 去除字符串两端空格

image-20211228183245600

function _trim(string) {
  return string.trim(); // 去除字符串两端的空格
}

FED35 输出日期

image-20211228205119898

function _date(number) {
  let date = new Date(number);
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  return `${year}-${month}-${day}`;
}

FED36 数字取整

image-20211228203315106

// 可以使用 ~~ 代替 Math.floor()
function _int(value) {
  return ~~value;
}

FED37 数组反转

image-20211228205608236

// 使用自带的数组反转函数
function _reverse(array) {
  return array.reverse();
}

// 从后往前遍历数组
function _reverse(array) {
  let res = [];
  for (let i = array.length - 1; i >= 0; i--) {
    res.push(array[i]);
  }
  return res;
}

FED38 数组转字符串

image-20211228205910420

// 直接使用自带的join() 函数
function _join(array) {
  return array.join("");
}

// 遍历拼接数组
function _join(array) {
  let res = "";
  array.forEach((item) => (res += item));
  return res;
}

FED39 数组最大值

image-20211228210309084

// 自带的函数方法
function _max(array) {
  return Math.max(...array);
}

// 遍历数组比较
function _max(array) {
  let max = array[0];
  array.forEach((i) => {
    if (i > max) {
      max = i;
    }
  });
  return max;
}

FED40 搜索数字

image-20211228213620500

// 字符串也可以使用...操作符
function _search(string) {
  return [...string].map((i) => parseInt(i)).some((i) => i >= 0 && i < 9);
}

FED41 头部插入元素

image-20211228213926761

// ES6写法
function _unshift(array, value) {
  return [value, ...array];
}

// 直接插入到数组头写法
function _unshift(array, value) {
  array.unshift(value);
  return array;
}

FED42 尾部插入元素

image-20211228214502819

// ES6写法
function _push(array, value) {
  return [...array, value];
}

// 直接push()写法
function _push(array, value) {
  array.push(value);
  return array;
}

FED43 Js-位置查找

image-20211228214821753

// indexOf() 方法
function _indexof(array, value) {
  return array.indexOf(value);
}

// 遍历
function _indexof(array, value) {
  for (let i of array) {
    if (array[i] == value) {
      return i;
    }
  }
  return -1;
}

FED44 向下取整

image-20211228215525453

function _floor(number) {
  return ~~number;
}

FED45 整数反转

image-20211228220336557

function _reverse(number) {
  let res = parseInt(Math.abs(number).toString().split("").reverse().join(""));
  return number >= 0 ? res : res * -1;
}

FED46 字符串搜索

image-20211229140329167

// 直接循环遍历字符串
function _search(string, value) {
  for (let i = 0; i <= string.length - 1; i++) {
    if (string[i] === value) {
      return true;
    }
  }
  return false;
}

// 字符串打散成为数组操作
function _search(string, value) {
  return [...string].includes(value);
}

// String.indexOf()返回调用它的String对象中第一次出现的指定值的索引
function _search(string, value) {
  return string.indexOf(value) !== -1;
}

FED57 移除数组中的元素

image-20211228172822096

// 遍历数组,找出其中不是目标的值
function remove(arr, item) {
  let res = [];
  arr.forEach((i) => {
    if (i !== item) {
      res.push(i);
    }
  });
  return res;
}

// 直接使用ES6中的filter( )过滤函数
function remove(arr, item) {
  return arr.filter((i) => i !== item);
}

FED58 移除数组中的元素

// 从后往前遍历数组!,遇到相等的就直接切掉当前数组
function removeWithoutCopy(arr, item) {
  for (let i = arr.length - 1; i >= 0; i--) {
    if (arr[i] == item) {
      arr.splice(i, 1);
    }
  }
  return arr;
}

FED59 添加元素

//方法一,声明空数组,遍历arr打入空数组,最后打入item
function append(arr,item){
  let tmp = []
  for(let i for arr){
    tmp.push(i);
  }
  tmp.push(item);
  return tmp;
}

//方法二,arr.slice()不带参数可以复制返回数组的副本
function append(arr,item){
	let tmp = arr.slice();
  tmp.push(item)
  return tmp;
}

//方法三,直接使用concat连接数组
function append(arr,item){
  return arr.concat([item]);
}

FED60 删除数组最后一个元素

//方法一,复制出新数组,末尾添加新元素
function truncafe(arr) {
  let tmp = arr.slice();
  tmp.pop();
  return tmp;
}

//方法二,arr.slice方法,返回新数组,原数组从头数第一个到从尾数倒数第二个切片
function truncafe(arr) {
  return arr.slice(0, -1);
}

FED61 添加元素

//方法一,拷贝出新数组,再添加元素到头部
function prepend(arr, item) {
  let tmp = arr.slice();
  tmp.unshift(item);
  return tmp;
}

//使用concat创建新数组并连接
function prepend(arr, item) {
  return [item].concat(arr);
}

// 展开运算符...
function prepend(arr, item) {
  return [item, ...arr];
}

FED62 删除数组的第一个元素

//方法一,使用slice()拷贝出新数组,在使用shift去除新数组的首位
function curtail(arr){
  let tmp = arr.slice();
  tmp.shift();
  return tmp;
}

//方法二,slice对数组切片
function curtail(arr) {
    return arr.slice(1);
}

//方法三,空数组concat连接后,相当于拷贝副本,在shift
fuction(arr){
  let tmp = arr.concat();
  tmp.shift();
  return tmp;
}

FED63 数组合并

image-20210722155256824

function concat(arr1, arr2) {
  return arr1.concat(arr2);
}
//concat方法返回的是新数组

FED64 添加元素

//利用slice和concat
function insert(arr, item, index) {
  return arr.slice(0, index).concat([item], arr.slice(index));
}

//利用slice拷贝在使用splice拼接替换
function insert(arr, item, index) {
  let tmp = arr.slice();
  tmp.splice(index, 0, item);
  return tmp;
}

FED65 求二次方

image-20210723155435049

//方法一,复制出一个数组出来,遍历此数组元素,对每个元素的值push到新数组中
function square(arr) {
  let tmp = arr.slice();
  let newArr = [];
  for (let i = 0; i < arr.length; i++) {
    newArr.push(tmp[i] * tmp[i]);
  }
  return newArr;
}

//方法二,拷贝出新数组后,shift取得首位,push到末尾执行数组length次
function square(arr) {
  let tmp = arr.slice();
  for (let i = 0; i < arr.length; i++) {
    let n = arr.shift();
    n *= n;
    tmp.push(n);
  }
  return tmp;
}

//方法三,使用数组的map方法,对数组的每一项回调返回平方
function square(arr) {
  return arr.map((item) => item * item);
}

// forEach():会修改原来的数组  ; map():得到一个新数组并返回

FED66 查找元素位置

image-20211228175337597

function findAllOccurrences(arr, target) {
  let res = [];
  arr.forEach((item, index) => {
    if (target == item) {
      res.push(index);
    }
  });
  return res;
}

FED68 正确的使用 parseInt

image-20210726142355840

//原题
function parse2Int(num) {
  return parseInt(num);
}

function parse2Int(num) {
  return parseInt(num, 10);
}

//parseInt(string, radix):string:需被解析的字符串,radix:要解析数字的基数,值在0~36之间

函数

FED47 函数——参数对象

image-20211229141126126

// 浏览器函数在调用的时候,会传递一个类数组对象参数: arguments.
function getArguments(a, b, c) {
  return [...arguments]; // 展开运算符将类数组对象转换成数组.
}

this

FED48 this 指向

image-20211229143912059

20.添加元素

image-20210901181712463

// 直接使用ES6的...spread展开操作符号
function append(arr, item) {
  return [...arr, item];
}

// 方法二 slice复制出一份,在push进去
function append(arr, item) {
  let res = arr.slice();
  res.push(item);
  return res;
}

26.计数

image-20210722163449677

// 数组遍历计数
function count(arr, item) {
  let count = 0;
  arr.forEach((i) => {
    if (i === item) {
      count++;
    }
  });
  return count;
}

// reduce遍历计数
function count(arr, item) {
  return arr.reduce((acc, val) => (val === item ? acc + 1 : acc), 0);
}

// filter过滤取长度
function count(arr, item) {
  return arr.filter((i) => i === item).length;
}

27.查找重复元素

image-20210722180804955

//关键是判断数组中间项和前项的位
function duplicates(arr) {
  let tmp = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] == arr[i + 1] && arr[i] !== arr[i - 1]) {
      tmp.push(arr[i]);
    }
  }
  return tmp;
}

查找数组元素

image-20210723182626339

//方法一,遍历数组,将遍历时索引给打入新数组
function findAllOccurrences(arr, target) {
  let tmp = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] == target) {
      tmp.push(i);
    }
  }
  return tmp;
}

//方法二,使用数组map方法,map方法最后返回的就是一个新数组
function findAllOccurrences(arr, target) {
  return arr.map((item, index) => {
    if (target == item) {
      return index;
    }
  });
}

避免全局变量

image-20210723190410320

//题目
function globals() {
  myObject = {
    name: "老王",
  };
  return myObject;
}

//函数内对象没有声明,直接变成全局变量,直接使用var或者let声明一下就好了
function globals() {
  let myObject = {
    name: "老王",
  };
  return myObject;
}

function golobals() {
  return { name: "老王" };
}

正确的函数定义

image-20210726131718017

//题目
function functions(flag) {
  if (flag) {
    function getValue() {
      return "a";
    }
  } else {
    function getValue() {
      return "b";
    }
  }

  return getValue();
}

//方法一,考察function 函数名 (){} 和 var 函数名 = function () {} 之间的区别
//前者是在执行前,就会被解析,后者是在执行过程中被解析
function functions(flag) {
  let getValue = null;
  if (flag) {
    getValue = function () {
      return "a";
    };
  } else {
    getValue = function () {
      return "b";
    };
  }
  return getValue();
}

//方法二
function functions(flag) {
  return flag ? "a" : "b";
}

计时器

image-20210726152853196

function count(start, end) {
  //立即输出第一个数
  console.log(start++);
  let timer = setIntval(() => {
    start <= end ? console.log(start++) : clearInterval(timer);
  }, 100);
  return { cancel: () => clearInterval(timer) };
}
//设置定时器后,计数器开始增加到结束后,清除定时器

空值合并运算符 ??

a ?? b 结果:

  • 如果 a 是已定义,则结果为 a
  • 如果 a 未定义,则结果为 b
let fruit;
console.log(fruit ?? "apple"); //apple
//变量声明后未赋值,返回 ?? 符号后面的参数

let fruit = "banana";
console.log(fruit ?? "apple"); //banana
//变量已经声明,返回原来的值

三元运算符 ?

let result = condition ? value1 : value2;
//如果condition条件为真则返回 值1,否则返回 值2;为了增加代码可读性,通常给判断语句加一层括号

let age = 20;
let info = age < 18 ? "未成年" : "成年人";
console.log(info);

//多重判断的运算符
let age = 34;
let message =
  age < 16
    ? "少年"
    : age < 18
    ? "未成年"
    : age < 25
    ? "青年"
    : age < 45
    ? "中年"
    : "老年";
console.log(message);
等价于;
if (age < 16) {
  message = "少年";
} else if (age < 18) {
  message = "未成年";
} else if (age < 25) {
  message = "青年";
} else {
  message = "老年";
}

流程控制

image-20210726172502644

function fizzBuzz(num) {
  return num % 3 === 0 && num % 5 === 0
    ? "fizzbuzz"
    : num % 3 === 0
    ? "fizz"
    : num % 5 === 0
    ? "buzz"
    : Object.prototype.toString.call(num) !== "[object Number]"
    ? false
    : num;
}
//使用Object.prototype.toString.call(num)来判断是否是number数据类型

知识点

typeof运算符返回参数的类型,两种使用方式

  • 直接作为运算符: typeof x
  • 函数形式: typeof(x)

有没有括号,两者结果差不多,使用 typeof x的调用会以字符串的形式返回数据类型;

typeof 12; // "number"
typeof "apple"; //"string"
typeof false; //"boolean"
let a = typeof 12;
typeof a; //"string",因为返回是字符串格式

使用 Object.prototype.toString.call() 来检测对象类型, typeof 不能准确判断对象变量

console.log(Object.prototype.toString.call("jerry")); //[object String]
console.log(Object.prototype.toString.call(12)); //[object Number]
console.log(Object.prototype.toString.call(true)); //[object Boolean]
console.log(Object.prototype.toString.call(undefined)); //[object Undefined]
console.log(Object.prototype.toString.call(null)); //[object Null]
console.log(Object.prototype.toString.call({ name: "jerry" })); //[object Object]
console.log(Object.prototype.toString.call(function () {})); //[object Function]
console.log(Object.prototype.toString.call([])); //[object Array]
console.log(Object.prototype.toString.call(new Date())); //[object Date]
console.log(Object.prototype.toString.call(/\d/)); //[object RegExp]
function Person() {}
console.log(Object.prototype.toString.call(new Person())); //[object Object]

二进制转换

image-20210728171600119

function base10(str) {
  return parseInt(str);
}

//parseInt(str,radix):将字符串读取数字,并以指定基数(radix)返回

二进制转换

image-20210728181338865

function converToBinary(num) {
  let tmp = num.toString(2);
  let len = tmp.length;
  return len < 8 ? "0".repeat(8 - len) + tmp : tmp;
}

二进制转换

image-20210901142704660

// 方法一 直接使用原生的方法,字符串转二进制 ==> 分割为数组 ==> 反转数组访问
function valueAtBit(num, bit) {
  return num.toString(2).split("").reverse()[bit - 1]; // 注意:最后返回值是string类型
}

// 方法二 模拟除法运算
function valueAtBit(num, bit) {
  let res = 0;
  for (let i = 0; i < bit; i++) {
    res = num % 2;
    num = parseInt(num / 2);
  }
  return res;
}

判断是否包含数字

image-20210729091258496

//遍历字符串,并且对每个字符串判断ASCII码值
function containsNumber(str) {
  for (let char of str) {
    if (char.charCodeAt() < 58 && char.charCodeAt > 47) {
      return false;
      break;
    }
  }
  return true;
}

//遍历字符串,使用 !NaN 判断是否为数字
function containsNumber(str) {
  for (let item of str) {
    if (!isNaN(item)) {
      return true;
    }
  }
  return false;
}

斐波那契数列第 n 项值

image-20210812144325644

// 方法一,新建初始数组,循环(n-1)次,每次将数组的倒数第一项与倒数第二项的和push进去,最后返回数组的pop
function fibonacci(n) {
  let arr = [0, 1];
  let i = 1;
  while (i < n) {
    arr.push(arr[arr.length - 2] + arr[arr.length - 1]);
    //还可以使用es6语法的arr.at()反向索引访问数组的值
    //arr.push(arr.at(-2) + arr.at(-1));
    i++;
  }
  return arr.pop();
}

//方法二,递归
function fibonacci(n) {
  return n < 3 ? 1 : fibonacci(n - 1) + fibonacci(n - 2);
}

//方法三,迭代
function fibonacci(n) {
  let start = 1,
    second = 1,
    end;
  for (let i = 3; i <= n; i++) {
    end = start + end;
    start = second;
    second = end;
  }
  return end;
}

使用 arguments

image-20210901140106457

function useArguments() {
  return Array.from(arguments).reduce((acc, item) => acc + item, 0);
}

柯里化

image-20210901152200855

// 函数柯里化: 把接受多个参数的函数变成接受多个单一参数的函数
function curryIt(fn) {
  return function(a) {
    return function(b) {
      return fucntion(c) {
        return a + b + c
      }
    }
  }
}

// 直接使用ES6的语法会更加简洁
let curryIt = fn => a => b => c => a + b + c

模块

image-20210901154742901

function createModule(str1, str2) {
  let obj = {
    greeting: str1,
    name: str2,
    sayIt: function () {
      return this.greeting + ", " + this.name;
    },
  };
  return obj;
}

数组去重

image-20210901160808677

// 遍历迭代去重
Array.prototype.uniq = function () {
  let res = [];
  this.forEach((item) => {
    if (!res.includes(item)) {
      res.push(item);
    }
  });
  return res;
};

// 利用set集合中的值唯一特性去重
Array.prototype.uniq = function () {
  return [...new Set(this)];
};

获取字符串的长度

image-20210901175430497

function strLength(s, bUnicode255For1) {
  if (bUnicode255For1) {
    return s.length;
  } else {
    return s
      .split("")
      .reduce((acc, item) => (item.charCodeAt() > 255 ? acc + 2 : acc + 1), 0);
  }
}
// reduce方法遍历到每个数组元素的时候,对累加器进行操作,最后返回累加器的值

前端大挑战

JS1 直角三角形

image-20220130102542119

var triangle = document.querySelector(".triangle");
let str = "";
for (let i = 0; i <= 3; i++) {
  for (let j = 0; j < i; j++) {
    str += "*";
  }
  str += "<br/>";
}
triangle.innerHTML = str;

JS5 创建数组

image-20220130102912401

const _createArray = (number) => {
  return new Array(number).fill(number);
};

JS7 无重复数组

image-20220130104617651

const _getUniqueNums = (start, end, n) => {
  var res = [],
    i = n;
  var randomNum = (start, end) => ~~(Math.random() * (end - start + 1)) + start;
  while (n) {
    res.push(randomNum(start, end));
    n--;
  }
  return res;
};

JS9 新数组

image-20220130105926868

const _delete = (array, index) => {
  let res = [];
  for (let item of array) {
    if (item === array[index]) continue;
    res.push(item);
  }
  return res;
};

JS10 计数器

image-20220130110621411

const closure = () => {
  let count = 1;
  return function () {
    return count++;
  };
};