牛客网JS能力测评经典题笔记

这是我在做完牛客网的45道JS能力测评经典题之后,结合他人的解析整理的一些笔记。如果有什么不对的地方,欢迎大家指出。

原试题地址

1. 查找数组元素位置

题目描述:
找出元素 item 在给定数组 arr 中的位置
输出描述:
如果数组中存在 item,则返回元素在数组中的位置,否则返回 -1
示例:
输入

[ 1, 2, 3, 4 ], 3

输出

2

function indexOf(arr, item) {
    return arr.indexOf(item);
}

这里用到了indexOf方法,返回指定的字符串值item在字符串arr中首次出现的位置。像本题中3出现在第3个位置,则返回2(从0开始算第一个位置)。如果要检索的字符串值item没有出现,则该方法返回 -1

2. 数组求和

题目描述:
计算给定数组 arr 中所有元素的总和
输入描述:
数组中的元素均为 Number 类型
示例:
输入

[ 1, 2, 3, 4 ]

输出

10

1.for循环

function sum(arr) {
    var s = 0;
    for (var i=0; i<arr.length; i++) {
        s = s+arr[i];
    }
    return s;
}

2.for in循环

function sum(arr) {
    var s = 0;
    for (var i in arr) {
        s = s+arr[i];
    }
    return s;
}

3.forEach

function sum(arr) {
    var s = 0;
    arr.forEach(function(val) {
        s = s+val;
    });
    return s;
}

1.for循环相信大家都能看懂,我就不在此赘述了。
2.for in循环用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。我觉得它相当于for循环的变体,也很好理解。
3.forEach方法用于调用数组的每个元素,并将元素传递给回调函数function。val是遍历数组arr时,当前指向的arr里的一个数组项元素,相当于arr[i]。若数组为空,则不执行回调函数function。结合for in循环,也很好理解。

3.移除数组中的元素(返回新的数组)

题目描述:
移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4, 2], 2

输出

[1, 3, 4]

function remove(arr, item) {
    var arr1 = [];
    arr.forEach(function(val) {
        if(val!=item){
            arr1.push(val);
        }
    });
    return arr1;
}

这道题和上一题一样可以用for循环和for in循环。push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。结合pop可以实现堆栈的后进先出。

4.移除数组中的元素(返回原数组)

题目描述:
移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回
示例:
输入

[1, 2, 2, 3, 4, 2, 2], 2

输出

[1, 3, 4]

function removeWithoutCopy(arr, item) {
    for(var i=0;i<arr.length;i++){
        if(arr[i]==item){
            arr.splice(i,1);
            i--;
        }
    }
    return arr;
}

splice(index,howmany,item1,…,itemX) 方法可删除从 index 处开始的howmany个元素,并且用参数列表中声明的一个或多个值item1,…,itemX来替换那些被删除的元素。在本题中,就是删除了从 i 处开始的1个元素。splice方法会改变数组的长度,当减掉一个元素后,后面的元素都会前移,因此在每次删除之后,都需要执行 i --。如果是用forEach或者for in循环,是不对的,因为splice改变数组长度,导致下一次索引位置错误,相当于for循环里去掉了 i --。

5.添加元素(末尾添加)

题目描述:
在数组 arr 末尾添加元素 item。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4], 10

输出

[1, 2, 3, 4, 10]

function append(arr, item) {
    var a=arr.slice(0);
    a.push(item);
    return a;
}

slice(start,end)方法可从已有的数组中返回一个新的数组,包含从 start 到 end (不包括该元素)的 arr 中的元素,其中end可省略不写,如果 end 未被规定,那么 slice() 方法会选取从 start 到数组结尾的所有元素。本题中则是返回从第一个位置到后面全部的元素,相当于把arr数组复制给a。

6.删除数组最后一个元素

题目描述:
删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4]

输出

[1, 2, 3]

function truncate(arr) {
    var a = arr.slice(0);
    a.pop();
    return a;
}

pop() 方法可删除并返回数组的最后一个元素。结合push可以实现堆栈的后进先出。

7.添加元素(开头添加)

题目描述:
在数组 arr 开头添加元素 item。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4], 10

输出

[10, 1, 2, 3, 4]

function prepend(arr, item) {
    var a = arr.slice(0);
    a.unshift(item);
    return a;
}

unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
补充:

unshift() 方法将把它的参数插入 arr数组的头部,并将已经存在的元素顺次地移到较高的下标处,以便留出空间。该方法的第一个参数将成为数组的新元素0,如果还有第二个参数,它将成为新的元素 1,以此类推。
unshift()方法不创建新的数组,而是直接修改原有的数组。
若要把一个或多个元素添加到数组的尾部,则使用 push() 方法。

8.删除数组第一个元素

题目描述:
删除数组 arr 第一个元素。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4]

输出

[2, 3, 4]

function curtail(arr) {
    var a = arr.slice(0);
    a.shift();
    return a;
}

shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
补充:

如果数组是空的,那么 shift() 方法将不进行任何操作,返回 undefined 值。
shift() 方法不创建新数组,而是直接修改原有的 arr数组。
若要删除并返回数组的最后一个元素,则使用 pop() 方法。

9.数组合并

题目描述:
合并数组 arr1 和数组 arr2。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4], [‘a’, ‘b’, ‘c’, 1]

输出

[1, 2, 3, 4, ‘a’, ‘b’, ‘c’, 1]

function concat(arr1, arr2) {
    return arr1.concat(arr2)
}

concat() 方法用于连接两个或多个数组。
补充:

该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本(新的数组)。
该数组是通过把所有 arrayX 参数添加到 arr 数组中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。

10.添加元素(指定位置添加)

题目描述:
在数组 arr 的 index 处添加元素 item。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4], ‘z’, 2

输出

[1, 2, ‘z’, 3, 4]

function insert(arr, item, index) {
    var a=arr.slice(0);
    a.splice(index,0,item);
    return a;
}

splice方法可参考第4题,在本题中,就是删除了从index处开始的0个元素,并用item来替换那些被删除的元素,相当于没有删除,直接在index处插入item。

11.计数

题目描述:
统计数组 arr 中值等于 item 的元素出现的次数
示例:
输入

[1, 2, 4, 4, 3, 4, 3], 4

输出

3

1.for循环

function count(arr, item) {
    var a=0;
    for(var i=0;i<arr.length;i++){
        if(arr[i]==item){
            a++;
        }
    }
    return a;
}

2.for in循环

function count(arr, item) {
    var a=0;
    for(var i in arr){
        if(arr[i]==item){
            a++;
        }
    }
    return a;
}

3.forEach

function count(arr, item) {
    var a=0;
    arr.forEach(function(val) {
        if(val==item){
            a++;
        }
    });
    return a;
}

本题的思路可以参考第2题,相信大家都能看懂,我就不在此赘述了。

12.查找重复元素

题目描述:
找出数组 arr 中重复出现过的元素
示例:
输入

[1, 2, 4, 4, 3, 3, 1, 5, 3]

输出

[1, 3, 4]

1.for循环

function duplicates(arr) {
    var b=[];
    arr.sort();
    for(var i=0;i<arr.length;i++){
        if(arr[i]==arr[i-1] && b.indexOf(arr[i])==-1){
            b.push(arr[i]);
        }
    }
    return b;
}

2.for in循环

function duplicates(arr) {
    var b=[];
    arr.sort();
    for(var i in arr){
        if(arr[i]==arr[i-1] && b.indexOf(arr[i])==-1){
            b.push(arr[i]);
        }
    }
    return b;
}

3.forEach

function duplicates(arr) {
    var b=[];
    arr.forEach(function(elem){
       if(arr.indexOf(elem) !=arr.lastIndexOf(elem) && b.indexOf(elem) == -1){
           b.push(elem);
       }
    });
    return b;
}

1.sort() 方法用于对数组的元素进行排序。这种排序,是按照字符编码的顺序进行排序。sort() 方法不创建新数组,而是直接修改原有的 arr数组。
2.lastIndexOf() 方法类似于 indexOf() 方法,只不过 lastIndexOf() 方法返回的是元素最后出现的位置,indexOf() 方法返回的是元素首次出现的位置。
3.第三个方法的思路,也可以用前面的for循环或者for in循环去替换forEach,有兴趣的小伙伴可以自己尝试一下。

13.求二次方

题目描述:
为数组 arr 中的每个元素求二次方。不要直接修改数组 arr,结果返回新的数组
示例:
输入

[1, 2, 3, 4]

输出

[1, 4, 9, 16]

function square(arr) {
    var a=[];
    for(var i in arr){
        a.push(arr[i]*arr[i]);
    }
    return a;
}

本题的思路相信大家都能看懂,我就不在此赘述了。

14.查找元素位置

题目描述:
在数组 arr 中,查找值与 item 相等的元素出现的所有位置
示例:
输入

‘abcdefabc’

输出

[0, 6]

function findAllOccurrences(arr, target) {
    var a=[];
    for(var i=0;i<arr.length;i++){
        if(arr[i]==target){
            a.push(i);
        }
    }
    return a;
}

本题的思路相信大家都能看懂,我就不在此赘述了。

15.避免全局变量

题目描述:
给定的 js 代码中存在全局变量,请修复
原代码:

function globals() {
    myObject = {
      name : 'Jory'
    };

    return myObject;
}

在Javascript语言中,声明变量使用的都是关键字var,如果不使用var而直接声明变量,则该变量为全局变量。

function globals() {
    var myObject = {
      name : 'Jory'
    };

    return myObject;
}

16.正确的函数定义

题目描述:
请修复给定的 js 代码中,函数定义存在的问题
示例:
输入

true

输出

a

原代码:

function functions(flag) {
    if (flag) {
      function getValue() { return 'a'; }
    } else {
      function getValue() { return 'b'; }
    }

    return getValue();
}

else中的语句相当于将if中的function重写,因此无论flag为何值,返回的方法始终为重写后的方法。将方法赋值给一个变量,方法就不会被重写,因此才能得到正确的结果。

function functions(flag) {
    if (flag) {
      var getValue = function () { return 'a'; }
    } else {
      var getValue = function () { return 'b'; }
    }

    return getValue();
}

17.正确的使用 parseInt

题目描述:
修改 js 代码中 parseInt 的调用方式,使之通过全部测试用例
示例:
输入

‘0x12’

输出

0

原代码:

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

parseInt(string, radix) 函数可解析一个字符串,并返回一个整数。参数 radix 表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,parseInt() 会根据 string 来判断数字的基数。
举例,如果 string 以 “0x” 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。
而本题则是要求解析为十进制的整数。

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

补充:

只有字符串中的第一个数字会被返回。
开头和结尾的空格是允许的。
如果字符串的第一个字符不能被转换为数字,那么 parseFloat() 会返回 NaN。
如果参数 radix 小于 2 或者大于 36,则 parseInt() 将返回 NaN。

18.完全等同

题目描述:
判断 val1 和 val2 是否完全等同

function identity(val1, val2) {
    if(val1===val2) {
        return true;
    }
    else{
        return false;
    }
}

一般使用双等来判断(= =),如果还需要类型相同那么就用三等(= = =)。

19.计时器

题目描述:
实现一个打点计时器,要求
1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
3、第一个数需要立即输出

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);
         }
     };
}

setInterval(code,millisec) 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。code 是要调用的函数或要执行的代码串,millisec 是周期性执行或调用 code 之间的时间间隔,以毫秒计。
setInterval() 方法会不停地调用 code 函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
clearInterval() 方法可取消由 setInterval() 设置的 timeout,其中的参数必须是由 setInterval() 返回的 ID 值。

20.流程控制

题目描述:
实现 fizzBuzz 函数,参数 num 与返回值的关系如下:
1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz
2、如果 num 能被 3 整除,返回字符串 fizz
3、如果 num 能被 5 整除,返回字符串 buzz
4、如果参数为空或者不是 Number 类型,返回 false
5、其余情况,返回参数 num
示例:
输入

15

输出

fizzbuzz

function fizzBuzz(num) {
    if(num%3==0 && num%5==0){
        return 'fizzbuzz';
    }
    else if(num%3==0){
        return 'fizz';
    }
    else if(num%5==0){
        return 'buzz';
    }
    else if(num==null || typeof num != 'number'){
        return false;
    }
    else{
        return num
    }
}

typeof 运算符返回一个字符串,表示未经计算的操作数的类型。
对变量或值调用 typeof 运算符将返回下列值之一:

  • undefined - 如果变量是 Undefined 类型
  • boolean - 如果变量是 Boolean 类型
  • number - 如果变量是 Number 类型
  • string - 如果变量是 String 类型
  • function - 如果变量是 函数对象
  • symbol - 如果变量是 Symbol 类型
  • object - 如果变量是一种引用类型或 Null 类型或任何其他对象

21.函数传参

题目描述:
将数组 arr 中的元素作为调用函数 fn 的参数
示例:
输入

function (greeting, name, punctuation) {return greeting + ', ’ + name + (punctuation || ‘!’);}, [‘Hello’, ‘Ellie’, ‘!’]

输出

Hello, Ellie!

function argsAsArray(fn, arr) {
    return fn.apply(this, arr);
}

function.apply(newObj[, argsArray]) 方法可以修改指定函数的调用对象。function 是调用对象将被修改的函数,newObj 是函数的新调用对象,argsArray 是传递给function函数的参数,数组或者arguments对象。
apply 方法是将传递给函数的参数放入一个数组中,传入参数数组即可。

22.函数的上下文

题目描述:
将函数 fn 的执行上下文改为 obj 对象
示例:
输入

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

输出

Hello, Rebecca!!!

1.apply

function speak(fn, obj) {
    return fn.apply(obj);
}

2.call

function speak(fn, obj) {
    return fn.call(obj);
}

function.call(newObj[, arg1[, arg2[, [,…argN]]]]) 方法的作用和 apply() 方法类似,只有一个区别,就是 call() 方法接受的是若干个参数的列表,而 apply() 方法接受的是一个包含多个参数的数组
将 fn 的执行上下文改为 obj 对象,也就是说把 fn 的方法放到 obj 上执行。这里涉及到作用域的知识,我还不是太了解,等我了解了相关的知识再修改这段文字。

23.返回函数

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

functionFunction(‘Hello’)(‘world’)

输出

Hello, world

function functionFunction(str) {
    return f = function (obj) {
        return str + ', ' + obj;
    }
}

首先执行functionFunction(‘Hello’),传入参数str,然后返回函数f,f与(‘world’)组合,执行f(‘world’),传入参数s,f返回str+", "+s,即Hello, world。注意中间的逗号后面有一个空格。
该函数只能接受两个参数,暂时没想到参数数目不定的实现方法,等我想到了实现方法再修改这段文字。

24.使用闭包

题目描述:
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 result[i] (),结果与 fn(arr[i]) 相同
示例:
输入

[1, 2, 3], function (x) {
return x * x;
}

输出

4

function makeClosures(arr, fn) {
    var result = [];
     arr.forEach(function(e){
         result.push(function(){
                 return fn(e);
         });
     });
     return result;
}

如果在函数 func 内部声明函数 inner ,然后在函数外部调用 inner ,这个过程即产生了一个闭包
这里是使用不了 for 循环和 for in 循环的,因为题目要求的是返回一个函数数组,如果在循环中直接写 result[i] = function(){return fn(arr[i]);} 或者 result.push(function(){return fn(arr[i]);}) ,最终的结果是不正确的,因为在每次迭代的时候,那样的语句后面的方法并没有执行,只是创建了一个函数体为“ return fn(arr[i]); ”的函数对象而已,当迭代停止时,i 为最终迭代停止的值,在函数被调用时,i 依旧为最终迭代停止的值,因此无法返回正确的结果。
所以对于函数数组,最好使用 forEach 循环。声明一个匿名函数,并立即执行它,function(){return fn(e); },函数执行后,e 立即传入,因此就能得到正确的结果。闭包允许你引用存在于外部函数中的变量。

25.二次封装函数

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

var sayIt = function(greeting, name, punctuation) { return greeting + ‘, ’ + name + (punctuation || ‘!’); }; partial(sayIt, ‘Hello’, ‘Ellie’)(’!!!’);

输出

Hello, Ellie!!!

function partial(fn, str1, str2) {
    return result = function (str3) {
        return fn(str1, str2, str3)
    };
}

因为没有要求函数内部this指向和作用域,所以可以不用 call 和 apply 方法。

26.使用 arguments

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

1, 2, 3, 4

输出

10

function useArguments() {
    var sum =0;
    for(var i in arguments){
        sum = sum + arguments[i];
    }
    return sum;
}

arguments能获得函数对象传入的参数组,类似于一个数组,包含传递给函数的每个参数,第一个参数在索引0处,能够通过length获取参数个数,能通过下标获取该位置的参数,但是它不能使用 forEach、pop 等方法。
arguments也可以被转换为一个真正的数组:

var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);

27.使用 apply 调用函数

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

function callIt(fn) {
    return fn.apply(this, [].slice.call(arguments, 1))
}

本题大家可以参考21题和上一题的知识点,我就不在此赘述了。

28.二次封装函数

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

function partialUsingArguments(fn) {
     //先获取p函数第一个参数之后的全部参数
     var args = [].slice.call(arguments,1);
     //声明result函数
     return result = function(){
         //使用concat合并两个或多个数组中的元素
         return fn.apply(this, args.concat( [].slice.call(arguments) ));
     };
}

本题的思路和上一题类似,我就不在此赘述了。

29.柯里化

题目描述:
已知 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

1.有arguments.callee

function curryIt(fn) {
     var args = [];
     return function(arg){
         args.push(arg);
         if(args.length < fn.length){
            return arguments.callee;
         }else 
            return fn.apply(this,args);
     }
 }

2.无arguments.callee

function curryIt(fn) {
     var args = [];
     var result = function(arg){
         args.push(arg);
         if(args.length < fn.length){
            return result;
         }else 
            return fn.apply(this,args);
     }
     return result;
 }

柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
arguments.callee 属性包含当前正在执行的函数。它可以用于引用该函数的函数体内当前正在执行的函数。这在函数的名称是未知时很有用,例如在没有名称的函数表达式 (也称为“匿名函数”)内。如第一个方法。
然而,这实际上是一个非常糟糕的解决方案,会导致一些意想不到的错误,(例如这样不能实现内联和尾递归,我没懂这一块,就没写上去)
我们可以通过命名函数表达式解决这些问题,这样的话该函数可以像代码内部的任何其他函数一样被调用,而且具有比访问arguments对象更好的性能。如第二个方法。

30.或运算

题目描述:
返回参数 a 和 b 的逻辑或运算结果
示例:
输入

false, true

输出

true

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

||为或运算。

31.且运算

题目描述:
返回参数 a 和 b 的逻辑且运算结果
示例:
输入

false, true

输出

false

function and(a, b) {
    return  (a && b);
}

&&为且运算(和运算)。

32.模块

题目描述:
完成函数 createModule,调用之后满足如下要求:
1、返回一个对象
2、对象的 greeting 属性值等于 str1, name 属性值等于 str2
3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ', ’ + name属性值

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

声明对象可以用 var obj = {};,可以直接在括号中以key:value的方式定义属性。

33.二进制转换(十进制转二进制)

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

128, 8

输出

1

function valueAtBit(num, bit) {
    var s = num.toString(2);
    return s[s.length - bit];
}

NumberObject.toString(radix) 方法可把一个 Number 对象转换为一个字符串,并返回数字的字符串表示。radix 表示数字的基数,为 2 ~ 36 之间的整数。若省略该参数,则默认使用基数 10。例如,当 radix 为 2 时,NumberObject 会被转换为二进制值表示的字符串。
补充:

当调用该方法的对象不是 Number 时抛出 TypeError 异常。

通过num.toString(2)能直接将num转换为2进制数格式的字符串,利用下标就能将对应值取出来。题目返回的数字是从右往左,因此下标为倒数。

34.二进制转换(二进制转十进制)

题目描述:
给定二进制字符串,将其换算成对应的十进制数字
示例:
输入

‘11000000’

输出

192

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

parseInt(string, radix) 函数可以参考17题,我就不在此赘述了。

35.二进制转换(十进制转8位二进制)

题目描述:
将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。
示例:
输入

65

输出

01000001

function convertToBinary(num) {
    var s = num.toString(2);
    while(s.length<8){
        s = '0'+s;
    }
    return s;
}

用字符串拼接来补0

36.乘法

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

3, 0.0001

输出

0.0003

function multiply(a, b) {
    return a*b;
}

37.改变上下文

题目描述:
将函数 fn 的执行上下文改为 obj,返回 fn 执行后的值
示例:
输入

alterContext(function() {return this.greeting + ', ’ + this.name + ‘!’; }, {name: ‘Rebecca’, greeting: ‘Yo’ })

输出

Yo, Rebecca!

function alterContext(fn, obj) {
    return fn.apply(obj);
}

38.批量改变对象的属性

题目描述:
给定一个构造函数 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;
}

prototype 属性可以向对象添加属性和方法。
这是原型链问题。访问一个对象的方法或者是属性,首先会在该对象中寻找,如果找到则返回,如果没找到,则在其原型链上面向上寻找,直至基原型,如还未找到,则返回undefined。将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量,只需要在constructor的原型上面添加greeting属性,并指定值。

39.属性遍历

题目描述:
找出对象 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 arr = [];
    //使用for-in遍历对象属性
    for(var key in obj){
        //判断key是否为对象本身的属性
        if(obj.hasOwnProperty(key)){
            //将属性和值按格式存入数组
            arr.push(key+": "+obj[key]);
        }
    }
    return arr;
}

obj.hasOwnProperty(prop) 方法会返回一个布尔值,指示对象 obj 自身属性中是否具有指定的属性 prop 。这个方法可以用来检测一个对象是否含有特定的自身属性,并忽略掉那些从原型链上继承到的属性
补充:

所有继承了 Object 的对象都会继承到 hasOwnProperty 方法。

const 定义的是常量( var 定义的是变量),常量不可以修改,而且必须初始化。
const arr = [];语句中,arr是个引用地址,这个地址不变,所以可以定义为常量。

40.判断是否包含数字

题目描述:
给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false
示例:
输入

‘abc123’

输出

true

function containsNumber(str) {
     return /\d/.test(str);
}

RegExpObject.test(string) 方法用于检测一个字符串是否匹配某个模式。如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。
RegExpObject 可以为正则表达式,\d 可以匹配数字字符。

41.检查重复字符串

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

‘rattler’

输出

true

function containsRepeatingLetter(str) {
    return /([A-Z])\1/i.test(str);
}

在正则表达式中,利用()进行分组,使用斜杠加数字表示引用,\1就是引用第一个分组,\2就是引用第二个分组。将[a-zA-Z]做为一个分组,然后引用,就可以判断是否有连续重复的字母。具体可以参考正则基础之——反向引用

42.判断是否以元音字母结尾

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

‘gorilla’

输出

true

function endsWithVowel(str) {
    return /[a,e,i,o,u]$/i.test(str);
}

首先确定元音集合[a,e,i,o,u],然后是以元音结尾,加上 $ ,最后通配大小写,加上 i ,因此正则表达式为: /[a,e,i,o,u]$/i 。

43.获取指定字符串

题目描述:
给定字符串 str,检查其是否包含 连续3个数字
1、如果包含,返回最新出现的 3 个数字的字符串
2、如果不包含,返回 false
示例:
输入

‘9876543’

输出

987

function captureThreeNumbers(str) {
    //声明一个数组保存匹配的字符串结果
    var arr = str.match(/\d{3}/);
    //如果arr存在目标结果,则返回第一个元素,即最早出现的目标结果
     if(arr)
          return arr[0];
     else return false;
}

string.match(RegExpObject) 方法可在字符串 string 内检索指定的值,或找到一个或多个正则表达式的匹配,并返回存放匹配结果的数组
补充:

若 RegExpObject 为普通字符串,此时match方法的返回值是存放首次匹配内容的数组。

连续的三个任意数字用正则表达式表示为 /\d{3}/ 。

44.判断是否符合指定格式

题目描述:
给定字符串 str,检查其是否符合如下格式
1、XXX-XXX-XXXX
2、其中 X 为 Number 类型
示例:
输入

‘800-555-1212’

输出

true

function matchesPattern(str) {
    //return/^(\d{3}-){2}\d{4}$/.test(str);
    return/^\d{3}-\d{3}-\d{4}$/.test(str);
}

本题需要注意格式,开头 ^ 和结尾 $ 必须加上来限定字符串,3个数可表示为\d{3},4个数则为\d{4},{n}表示前面内容出现的次数。正则表达式可写作 /^ \d{3}-\d{3}-\d{4}$ / ,有相同部分\d{3}-,因此也可写作 /^(\d{3}-){2}\d{4}$/ 。

45.判断是否符合 USD 格式

题目描述:
给定字符串 str,检查其是否符合美元书写格式
1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用 , 分隔
3、如果为小数,则小数部分长度为 2
4、正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12 或者 $34,344.3
示例:
输入

‘$20,933,209.93’

输出

true

function isUSD(str) {
    return/^\$( [1-9]\d{0,2}(,\d{3})*|0 )(\.\d{2})?$/.test(str);
}

首先,开头必是 $ ,而正则表达式中 $ 表示结尾,需要进行转义,因此开头为 ^\$ 。
然后$后必然接数字,开头第一个数字为1-9,并且最少一位,最多三位数,可用{m,n}表示,最少m位,最多n位,因此此段为 [1-9] \d{0,2} 。
接着,后面如还有数,则必然有,分隔,并且后面必有3个数,类似于,XXX的格式会出现0或者n次,因此此段可表示为 (,\d{3})* 。
另外,还要考虑整数部分为0的情况,则要加上 |0 。
最后,如有小数部分,则注意对小数点进行转义,此段可表示为(\.\d{2})? 。
因此,最后的正则表达式为 /^\$([1-9]\d{0,2}(,\d{3})*|0)(\.\d{2})?$/ 。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值