一些题

来源:互联网 发布:福建公安便民网络 编辑:程序博客网 时间:2024/06/07 14:14

移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回

方法一:

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


removeWithoutCopy([1, 2, 2, 3, 4, 2, 2],2);


方法二:

function removeWithoutCopy(arr, item) {
    for(i=arr.length-1;i>=0;i--)
      {
       if(arr[i]==item)
         {
                    arr.splice(i,1);
          }
       }
    return arr;
}
倒着检测;不用考虑;位置影响吧

在数组 arr 末尾添加元素 item。不要直接修改数组 arr,结果返回新的数组
方一:
var append = function(arr, item) {
    varlength = arr.length,
        newArr = [];
 
    for(vari = 0; i < length; i++) {
        newArr.push(arr[i]);
    }
 
    newArr.push(item);
 
    returnnewArr;
};
方二:
/**
 * 使用slice浅拷贝+push组合
 * @param arr
 * @param item
 * @returns {Blob|ArrayBuffer|Array.<T>|string}
 */
var append2 = function(arr, item) {
    varnewArr = arr.slice(0); // slice(start, end)浅拷贝数组
    newArr.push(item);
    returnnewArr;
};

方三:
/**
 * 使用concat将传入的数组或非数组值与原数组合并,组成一个新的数组并返回
 * @param arr
 * @param item
 * @returns {Array.<T>|string}
 */
var append3 = function(arr, item) {
    returnarr.concat(item);
};



在数组 arr 开头添加元素 item。不要直接修改数组 arr,结果返回新的数组

方一:
function prepend(arr, item){
   var arr1=[item];
   return arr1.concat(arr);
}


prepend([1, 2, 3, 4], 10);


方二:
function prepend(arr, item) {
     //将arr数组复制给a
     var a = arr.slice(0);
     //使用unshift方法向a开头添加item
     a.unshift(item);
     returna;
 }


找出数组 arr 中重复出现过的元素
方一:
function duplicates(arr) {
    var new_arr = arr.sort();//先把arr排序
    var res = [] ;//目标容器
    for( var i = 0 ; i < new_arr.length ; i++){
        if(new_arr[i] == new_arr[i+1] && new_arr[i] !=new_arr[i-1]){//判断是否重复,是否已经放入容器
            res.push(new_arr[i]);
        }
    }
return res;
}

方二

function duplicates(arr) {
 varresult = [];
    arr.forEach(function(elem){
       if(arr.indexOf(elem) !=arr.lastIndexOf(elem) && result.indexOf(elem) == -1){
           result.push(elem);
       }
    });
    returnresult;
}

duplicates([1, 2, 4, 4, 3, 3, 1, 5, 3]);

方三:
function duplicates(arr) {
    // console.log("11112");
    arr.sort();
    var result=[];
    var now;
    for(var i=0;i<arr.length;i++){
        now=arr[i];
        if(result.indexOf(now)==-1){
            console.log(now);
            for(var j=i+1;j<arr.length;j++){
                if(arr[j]==now){
                    result.push(now);
                    break;
                }
            }
       }
    }
    console.log(result);
    return result;
}


duplicates([1, 2, 4, 4, 3, 3, 1, 5, 3]);


实现一个打点计时器,要求
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);
         }
     };
 }

方二:(自己写的)
function count(start, end) {
    var now=start;
    console.log(now);
    var time=setInterval(function(){
        if(now<end){
            now++;
            console.log(now);
        }else{
            clearInterval(time);
        }
        
    },100)
    this.cancel=function(){
        clearInterval(time);
    }
    
    return this;
}
方法三:使用递归的方法用setTimeout替代setInterval
function count(start, end) {
    if(start <= end){
        console.log(start);
        start++;
        st = setTimeout(function(){count(start, end)}, 100);
    }
    return{
        cancel:function(){clearTimeout(st);}
    }
}


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

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

实现阶乘的函数
方一:
function factorial(num){
      if(num<=1){
           return 1;
      }else{
          return num*factorial(num-1);
      }
}

方法二:
function factorial(num){
      if(num<=1){
           return 1;
      }else{
          return num*arguments.callee(num-1);
      }
}


将函数 fn 的执行上下文改为 obj 对象
改变函数this指向的3中方法,注意函数的上下文!=this
方法一:
//apply
function speak(fn, obj) {
    returnfn.apply(obj);
}
方法二:
//call
function speak(fn, obj) {
    returnfn.call(obj);
}
方法三:
//bind
function speak(fn, obj) {
    returnfn.bind(obj)();
}


使用闭包

题目描述

实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同
解析:一般如果不了解es5中没有块级作用域的话就会写成
function makeClosures(arr, fn) {
    var result=[];
    for(var i=0;i<arr.length;i++){
      result.push(function(){
            return fn(arr[i])//由于js不像其他的如c语言等有块级作用域的概念。所以for循环执行完了以后所有的i都是指同一个i=arr.length-1;详细解释见高程p181
     })
    }
    return result;
}
解决办法
方一:使用立即执行函数
function makeClosures(arr, fn) {
    var result=[];
    for(var i=0;i<arr.length;i++){
       (function(i){
           result.push(function(){
               return fn(arr[i]);
           });
       })(i)
    }
    return result;
}


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

方法二:使用es6的let
function makeClosures(arr, fn) {   
    var result = new Array();
    for(let i=0;i<arr.length;i++){
        result[i] = function(){
            returnfn(arr[i]);//let声明的变量只在let所在代码块内有效,因此每次循环的i都是一个新的变量           
        };
    }
    return result;
}

方法三:
//参考《JavaScript高级程序设计》的典型方法
function makeClosures(arr, fn) {
    varresult =newArray();
    for(vari=0;i<arr.length;i++){
        result[i] =function(num){
            returnfunction(){
                returnfn(num);
                 
            }
        }(arr[i]);
    }
    returnresult;
}

方法四:
//使用forEach()
function makeClosures(arr, fn) {
    varresult =newArray();
    arr.forEach(function(curr){
        result.push(function(){returnfn(curr)});//注这个的curr每一个都是不同的
    })
    returnresult;
}


方法五:
//使用ES5的bind()方法
function makeClosures(arr, fn) {
    varresult =newArray();
    for(vari=0;i<arr.length;i++){
        result[i] = fn.bind(null,arr[i]);
    }
    returnresult;
}


二次封装函数

题目描述

已知函数 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) {
    var result;
    result=function(str3){
        return fn(str1,str2,str3);
    }
    return result;
}
var sayIt = function(greeting, name, punctuation) {     
    return greeting + ', ' + name + (punctuation || '!'); 
};  
partial(sayIt, 'Hello', 'Ellie')('!!!');


方法二:(并不懂这里用call是为了什么感觉多此一举,因为根据作用域链,是可以直接获取到str1和str2的

// call
function partial(fn, str1, str2) {
    functionresult(str3) {
        returnfn.call(this, str1, str2, str3);
    }
 
     returnresult;
}
 方法二:(并不懂这里用apply是为了什么感觉多此一举)
// apply(这里只是为了对照)
function partial(fn, str1, str2) {
    functionresult(str3) {
        returnfn.apply(this, [str1, str2, str3]);
    }
 
    returnresult;
}
 方法三:
// 这个bind会生成一个新函数对象, 它的str1, str2参数都定死了, str3未传入, 一旦传入就会执行
function partial(fn, str1, str2) {
    returnfn.bind(this, str1, str2);// 或 return fn.bind(null, str1, str2);
}
 方法四:
// bind同上, 多了一步, 把str3传入的过程写在另一个函数里面, 而另一个函数也有str1, str2参数
function partial(fn, str1, str2) {
    functionresult(str3) {
        returnfn.bind(this, str1, str2)(str3);
    }
 
    returnresult;
}
 方法五:
// 匿名函数
function partial(fn, str1, str2) {
    returnfunction(str3) {
        returnfn(str1, str2, str3);
    }
}
方法六:
// ES6
const partial = (fn, str1, str2) => str3 => fn(str1, str2, str3);


使用arguments

题目描述

函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。
方法一:
function useArguments() {
    var sum=0;
    for(var i=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
    return sum;
}
useArguments(1, 2, 3, 4);

方法二:
function useArguments() {
    vararr=Array.prototype.slice.call(arguments)//把arguments类数组转化为数组,转化为数组后才可以用数组的方法。
    returneval(arr.join("+"));//求和
}
方法三:
function useArguments() {
    varresult = Array.prototype.reduce.call(arguments,function(a,b){returna+b;});
    returnresult;
}

方法四:
function useArguments() {
    returnArray.prototype.slice.call(arguments).reduce(function(pre,cur,i,a){
        returnpre + cur;
    });
}

使用apply调用函数

题目描述

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