前端JS编程

140 阅读7分钟

可前到牛客网去刷题:牛客网前端大挑战

FED1 修改this指向

封装函数 f,使 f 的 this 指向指定的对象 题解:

function bindThis(f, oTarget) {
    return function(x,y){//方法1
        return f.call(oTarget,x,y)
    }
    return f.bind(oTarget)//方法2
    return function(){//方法3
        return f.apply(oTarget,arguments)        
    }
}

FED2 获取 url 参数

获取 url 中的参数\

  1. 指定参数名称,返回该参数的值 或者 空字符串
  2. 不指定参数名称,返回全部的参数对象 或者 {}
  3. 如果存在多个同名参数,则返回数组
  4. 不支持URLSearchParams方法
输入:
http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key
输出:
[1, 2, 3]

题解

function getUrlParam(sUrl, sKey) {
    let paramArr = sUrl.split('?')[1].split('#')[0].split('&');
    const obj = {};
    paramArr.forEach(item=>{
        const [key,value] = item.split('=');
        if(obj[key] === undefined){
            obj[key] = value;
        }else{
            obj[key] = [].concat(obj[key],value);
        }
    })
    return !sKey ? obj:obj[sKey] || ''    
}

FED3 dom 节点查找

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

输入描述:

oNode1 和 oNode2 在同一文档中,且不会为相同的节点

function commonParentNode(oNode1, oNode2) {
    if(oNode1.contains(oNode2)){
        return oNode1;
    }
    if(oNode2.contains(oNode1)){
        return oNode2;
    }
    while(true){
        oNode1 = oNode1.parentNode;
        if(oNode1.contains(oNode2)){
            return oNode1;
        }
    }
}

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

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

输入描述:

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

输出描述:

{a: {test: 1, b: {c: {d: {}}}}}

题解


function namespace(oNamespace, sPackage) {
    let o = sPackage?sPackage.split('.'):[];
    console.log(o)
    for(let i in o){
        if (Object.prototype.toString.call(oNamespace[o[i]])  !== '[object Object]'){
       // if(typeof  oNamespace[o[i]] !== 'object'){
            oNamespace[o[i]] = {};
        } 
        oNamespace = oNamespace[o[i]] ;
    }
    
    return oNamespace
}

FED7 时间格式化输出

按所给的时间格式输出指定的时间
格式说明
对于 2014.09.05 13:14:20
yyyy: 年份,2014
yy: 年份,14
MM: 月份,补满两位,09
M: 月份, 9
dd: 日期,补满两位,05
d: 日期, 5
HH: 24制小时,补满两位,13
H: 24制小时,13
hh: 12制小时,补满两位,01
h: 12制小时,1
mm: 分钟,补满两位,14
m: 分钟,14
ss: 秒,补满两位,20
s: 秒,20
w: 星期,为 ['日', '一', '二', '三', '四', '五', '六'] 中的某一个,本 demo 结果为 五

输入:
formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')
输出:
2014-09-05 13:14:20 星期五

题解

function formatDate(date,format){
    let addZero = function(data){
        return ('0'+data).slice(-2);
    }
    let obj = {
        'yyyy':date.getFullYear(),
        'yy':date.getFullYear() % 100,
        'MM':addZero(date.getMonth()+1),
        'M':date.getMonth()+1,
        'dd':addZero(date.getDate()),
        'd':date.getDate(),
        'HH':addZero(date.getHours()),
        'H':date.getHours(),
        'hh':addZero(date.getHours()%12),
        'h':date.getHours()%12,
        'mm':addZero(date.getMinutes()),
        'm':date.getMinutes(),
        'ss':addZero(date.getSeconds()),
        's':date.getSeconds(),
        'w':function(){
            arr = ['日', '一', '二', '三', '四', '五', '六'];
            return arr[date.getDay()];
        }()
    }
    for(let i in obj){
        format = format.replace(i,obj[i]);
    }
    return format;
}

FED6 斐波那契数列

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

题解

function fibonacci(n) {
    if(n===1 || n===2){
        return 1;
    }
    return arguments.callee(n-1) + arguments.callee(n-2);
    //return fibonacci(n-1) + fibonacci(n-2)
}

FED39 使用闭包

实现函数 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) {
    let result = [];
    for(let i = 0;i < arr.length; i++){
       result[i] = fn.bind(this,arr[i]);
    }
    return result;
}

FED32 正确的使用 parseInt

## 示例1
输入:'12' 
输出: 12 
## 示例2 
输入: '12px' 
输出: 12 
## 示例3 
输入: '0x12' 
输出: 0

解答

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

乘法

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

输入:
3, 0.0001
输出:
0.0003

解答:

function multiply(a, b) {
    let str1 = a.toString().split('.')[1] || '';
    let str2 = b.toString().split('.')[1] || '';
    return (a*b).toFixed(str1.length + str2.length);
} 

数组相关题

FED23 删除数组第一个元素

删除数组 arr 第一个元素。不要直接修改数组 arr,结果返回新的数组

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

输出:
[2, 3, 4]

解答:

//使用shift()
function curtail3(arr) {
    //let newArr = arr.slice(0);//返回一个新的数组
    let newArr = [...arr]; //性能更好
    newArr.shift();
    return newArr;
}
//使用filter函数过滤
function curtail(arr) {
    return arr.filter(function (ele,i) {
        return i != 0;
    });
}
function curtail5(arr) {    
    return arr.slice(1);
}
//使用splice切除第一个元素
function curtail4(arr) {    
    var newArr = arr.slice(0);
    return newArr.slice(1);
}
function curtail2(arr) {
    const [,...rest] = arr;
    return rest;
}

FED23 删除数组最后一个元素

删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组

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

输出:
[1, 2, 3]

题解:

function truncate2(arr) {
    let newArr = [...arr];
    newArr.pop();
    return newArr;
}
function truncate3(arr) {
    let newArr = arr.slice(0,arr.length-1);
    return newArr;
}
function truncate(arr) {
    let newArr = [];
    newArr = arr.filter((item,index)=>{
        return item != arr.length;
    })
    return newArr;
}

FED18 移除数组中的元素

移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组

题解:

function remove(arr, item) {
    return arr.filter(itemarr => {
        return itemarr !== item;
    })
};
function remove2(arr, item) {
    let newArr=[];
    for(let i = 0; i < arr.length; i++){
        if(arr[i] !== item){
            newArr.push(arr[i]);
        }
    }
    return newArr;
};

FED19 移除数组中的元素

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

题解:

function removeWithoutCopy(arr, item) {
    for(let i = arr.length-1; i >= 0; i--){
        if(arr[i] === item){
            arr.splice(i,1);
        }
    }
    return arr;
}
function removeWithoutCopy3(arr, item) {
    for(let i = 0; i < arr.length; i++){
        if(arr[i] === item){
            arr.splice(i,1);
            i--;
        }
    }
    return arr;
}
function removeWithoutCopy2(arr, item) {
    while(arr.indexOf(item) !== -1){
        arr.splice(arr.indexOf(item),1);
    }
    return arr;
}

FED20 添加元素

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

题解:

function append(arr, item) {
    let newArr = [...arr]; //arr.slice(0);
    newArr.push(item);
    return newArr;
}
function append2(arr, item) {
    return arr.concat(item);
}

FED22 添加元素

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

解答:

function prepend(arr, item) {
    let newArr = arr.slice(0);
    newArr.unshift(item);
    return newArr;
}
function prepend3(arr, item) {
    let newArr = [item];
    return newArr.concat(arr);
}
function prepend2(arr, item) {
    return [item,...arr]
}

FED25 添加元素

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

示例

输入:
[1, 2, 3, 4], 'z', 2
输出:
[1, 2, 'z', 3, 4]

题解:

function insert(arr, item, index) {
    let newArr = arr.slice(0);
    newArr.splice(index,0,item);
    return newArr;
}
function insert2(arr, item, index) {
    let newArr = arr.slice(0,index);
    let lastArr = arr.slice(index,arr.length);
    return [...newArr,item,...lastArr];
}

FED27 查找重复元素

找出数组 arr 中重复出现过的元素(不用考虑返回顺序)

解答:

//1、利用 indeOf 与 lastIndexOf 的返回值不一致,判断重复出现过:
function duplicates2(arr) {
    let res = [];
    for(let i = 0; i < arr.length; i++){
        if(res.indexOf(arr[i])===-1 && 
          arr.indexOf(arr[i]) !== arr.lastIndexOf(arr[i])){
            res.push(arr[i]);
        }
    }
    return res;
}
//2、直接使用filter + index + lastIndexOf 去判断重复:
function duplicates3(arr) {
    return arr.filter((item,index)=>{
        return arr.lastIndexOf(item) !== index &&
            arr.indexOf(item) === index
    })
}
//3、利用数组排序,然后通过对比当前元素与后一个相同但与前一个不同去找到重复出现的元素:
function duplicates(arr) {
    let newArr = arr.sort();
    return newArr.filter((item,index)=>{
        return item === newArr[index+1] && item !== newArr[index-1]
    })
}

FED16 查找数组元素位置

找出元素 item 在给定数组 arr 中的位置

输出描述:

如果数组中存在 item,则返回元素在数组中的位置,否则返回 -1

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

输出:
2

解答:

function indexOf(arr, item) {
    if(!arr || !arr.length){
        return -1;
    }
    if(Array.prototype.indexOf){
        return arr.indexOf(item);
    }
    for(let i = 0; i < arr.length; i++){
        /*if(arr[i] === item){
            return i;
        }*/
        //支持arr[i]为对象,数组等
        if(JSON.stringify(arr[i]) === JSON.stringify(item)){
            return i ;
        }
    }
    return -1;
}

FED29 查找元素位置

为 Array 对象添加一个去除重复项的方法

示例

输入:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]
输出:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']

题解

function findAllOccurrences(arr, target) {
    let res = [],n = 0;
    let newArr = arr.slice(0);
    while(newArr.indexOf(target,n)!== -1){   
        res.push(newArr.indexOf(target,n));
        n = newArr.indexOf(target,n) + 1;   
    }
    return res;
}

let res = findAllOccurrences('abcdeafabc'.split(''), 'a')
console.log(res)// 0 5 7

FED5 数组去重

为 Array 对象添加一个去除重复项的方法

输入:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]
输出:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']

题解

Array.prototype.uniq = function () {
    let res = [];
    this.forEach(item=>{
        if(!res.includes(item)){
            res.push(item);
        }
    })
    return res;
}
Array.prototype.uniq4 = function () {
    return Array.from(new Set(this));
}
Array.prototype.uniq3 = function () {
    return [...new Set(this)];
}
Array.prototype.uniq2 = function () {
    let newArr = new Set(this);
    return [...newArr];
}

字符串相关 + 正则

FED8 获取字符串的长度

如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1
否则如果字符 Unicode 编码 > 255 则长度为 2

输入:
'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;
}
function strLength2(s, bUnicode255For1) {
    if(bUnicode255For1){
        return s.length;
    }
    let sum = 0;
    for(i in s){
        if(s.charCodeAt(i) > 255){
            sum += 2;
        }else{
            sum += 1;
        }
    }
    return sum;
}

FED10 颜色字符串转换

将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff

  1. rgb 中每个 , 后面的空格数量不固定
  2. 十六进制表达式使用六位小写字母
  3. 如果输入不符合 rgb 格式,返回原始输
输入:
'rgb(255, 255, 255)'
输出:
#ffffff

题解:

function rgb2hex(sRGB) {
    // 去除 sRGB 的空格
    const newSRGB = sRGB.replace(/\s+/g,"");
    // 定义 rbg 的正则表达式(正则数字0-999),后面需要判断
    const regexp = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/
    let ret = newSRGB.match(regexp);
    if(!ret){
        return sRGB;
    }
    // 剔除 'rgb(' 和 ')', 剩下 'xx,xx,xx' 的字符串
    let arr = sRGB.slice(4,sRGB.length-1).split(",");
    
    let color = '#'
    // 遍历数组,将每个元素转成16进制的字符串
    for (const item of arr) {
        console.log(item)
        if(item < 0 || item > 255){
            return sRGB;
        }
        const str = Number(item).toString(16)
        color += str.length === 1 ? `0${str}` : str ;
    }
    return color;
}

FED58 获取指定字符串

给定字符串 str,检查其是否包含 连续3个数字
1、如果包含,返回最先出现的 3 个数字的字符串
2、如果不包含,返回 false

输入:
'9876543'
输出:
987

解答

function captureThreeNumbers(str) {
    let reg = /\d{3}/g;
    let res = str.match(reg);
    return res?res[0]:false;
} 
/* exec  test   match
function test(str) {
    let reg = /\d{3}/g;
    var arr = reg.exec(str);
    console.log(arr); //['987', index: 0, input: '9876566455', groups: undefined]

    let r =  reg.test(str);
    console.log(r); //true 

    let res = str.match(reg);
    console.log(res); // ['987', '656', '645']

    return res?res[0]:false;
} 
test('9876566455')
*/

FED55 判断是否包含数字

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

输入:
'abc123'
输出:
true

解答:

function containsNumber(str) {
    for(let i=0;i<10;i++) {
        if(str.indexOf(i)!==-1) return true
    }
    return false
} 
function containsNumber3(str) {
    return (/\d/.test(str));
}
function containsNumber2(str) {
    let reg = /\d/g;
    if(reg.test(str)){
        return true;
    }
    return false;
} 
function containsNumber5(str) {
    return str.search(/\d/) !== -1
}

FED9 邮箱字符串判断

判断输入是否是正确的邮箱格式

输入描述:
邮箱字符串

输出描述:
true表示格式正确
function isAvailableEmail(sEmail) {
    var reg=/^([\w+\.])+@\w+([.]\w+)+$/;
    return reg.test(sEmail);
}
/*
知识点: 
1.  匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
2 [abc]: 匹配 a 或 b 或 c
正则: /^([\w+\.])+@\w+([.]\w+)+$/;

分析:
122_.123@qq.com.cm
([\w+\.])+:等同于[a-zA-Z0-9_\.],也就是a-zA-Z0-9_.任意其中一个就是匹配到的,所以不一定要有.;(理解中括号的正则) 例子中匹配到的部分:122_.123
@: 匹配到@
\w+: 一个或多个[a-zA-Z0-9_],例子中匹配的部分:qq(也就是以\w开头的,注意这里没有点)
([.]\w+)+: 以点开头的,后跟一个或多个[a-zA-Z0-9_]:例子匹配到的部分:.com、.cm
$: 结束符(懂的人:这是废话)
*/

FED57 判断是否以元音字母结尾

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

输入:
'gorilla' 
输出: 
true

解答

function endsWithVowel(str) {
    let reg = /([aeiou])$/i;
    return reg.test(str)
}

FED11 将字符串转换为驼峰格式

css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能\

  1. 以 - 为分隔符,将第二个起的非空单词首字母转为大写\
  2. -webkit-border-image 转换后的结果为 webkitBorderImage
输入:
'font-size'
输出:
fontSize

题解:

function cssStyle2DomStyle(sName) {    
    //split切割函数
    var arr = sName.split('');
    //判断第一个是不是 - ,是的话就删除、
    if(arr.indexOf('-') ==0 ){
        arr.splice(0,1);
    }
    //处理剩余的 -
    for(var i = 0;i < arr.length; i++){
        if(arr[i] == '-'){
            arr.splice(i ,1);
            arr[i] = arr[i].toUpperCase();
        }
    }
    //根据某个字符将数组转成字符串
    return arr.join('');
}

FED59 判断是否符合指定格式

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

输入:
'800-555-1212'
输出:
true

题解

function matchesPattern(str) {    
    //^表示匹配输入字符串的开始位置,$表示匹配输入字符串的结束位置
    //不加的话会通过如下字符串:"a800-555-1212b"
    let reg = /^\d{3}-\d{3}-\d{4}$/
    return reg.test(str);
}

FED56 检查重复字符串

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

输入:
'rattler' 
输出: 
true

题解

function containsRepeatingLetter(str) {
    /*在正则表达式中,利用()进行分组,使用斜杠加数字表示引用,
    \1就是引用第一个分组,\2就是引用第二个分组。
    将[a-zA-Z]做为一个分组,然后引用,就可以判断是否有连续重复的字母。
    */
    let reg = /([a-zA-Z])\1/
    return reg.test(str)
}

FED12 字符串字符统计

统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率

  1. 不限制 key 的顺序
  2. 输入的字符串参数不会为空
  3. 忽略空白字符
输入:
'hello world' 
输出: 
{h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1}

题解

function count(str) {
    let obj = {};
    for(let i = 0;i < str.length; i++){
        let key = str[i];
        if(key === ' ') continue;
        if(obj[key] !== undefined){
            obj[key] += 1;
        }else{
            obj[key] = 1;
        }
    }
    return obj;
}
function count2(str) {
    let obj = {};
    for(let i = 0; i < str.length; i++){
        if(str.charAt(i) === '') continue;
        if(!obj[str.charAt(i)]){
            obj[str.charAt(i)] = 1;
        }else{
            obj[str.charAt(i)] += 1;
        }
    }
    return obj;
}

FED60 判断是否符合 USD 格式

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

输入:
'$20,933,209.93' 
输出: 
true

题解:

function isUSD(str) {
    let reg = /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/;
    return reg.test(str)
}

函数相关

FED37 函数的上下文

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

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

输出: 
Hello, Rebecca!!!

解答

function speak(fn, obj) {
    return fn.apply(obj); 
} 
function speak2(fn, obj) {
    return fn.call(obj); 
} 
function speak3(fn, obj) {
    return fn.bind(obj)(); 
} 

FED42 使用 apply 调用函数

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

function callIt(fn) {
    let args = Array.prototype.slice.call(arguments,1);
    return fn.apply(null,args);
}

解析 : 参考链接:www.jianshu.com/p/ae57baecc…

`[].slice.call(arguments)`能将具有`length`属性的对象转成数组:
**补充: **
将函数的实际参数转换成数组的方法

方法一:`var args = Array.prototype.slice.call(arguments);`

方法二:`var args = [].slice.call(arguments, 0);`

方法三: 

var args = []; 
for (var i = 1; i < arguments.length; i++) { 
    args.push(arguments[i]);
}

最后,附个转成数组的通用函数 

var toArray = function(s){
    //try语句允许我们定义在执行时进行错误测试的代码块。
   //catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
    try{
        return Array.prototype.slice.call(s);
    } catch(e){
        var arr = [];
        for(var i = 0,len = s.length; i < len; i++){
            //arr.push(s[i]);
               arr[i] = s[i];  //据说这样比push快
        }
         return arr;
    }
}

作者:hanyuntao
链接:https://www.jianshu.com/p/ae57baecc57d\
来源:简书

FED36 函数传参

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

输入:
function (greeting, name, punctuation) {
    return greeting + ', ' + name + (punctuation || '!');
},
['Hello', 'Ellie', '!']
输出:
Hello, Ellie!

题解

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

FED52 改变上下文

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

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

题解

function alterContext3(fn, obj) {
    return fn.bind(obj)(); //返回的是一个函数,要立即执行
}
function alterContext(fn, obj) {
    return fn.call(obj);
    return fn.call(obj,obj);
}
function alterContext34(fn, obj) {
    return fn.apply(obj,obj);
    return fn.apply(obj);
}

FED40 二次封装函数

已知函数 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 partial4(fn, str1, str2) {
    return function result(str3){
        return fn.call(this,str1,str2,str3);
    }
}
function partial(fn, str1, str2) {
    return function result(str3){
        return fn.apply(this,[str1,str2,str3]);
    }
}

FED43 二次封装函数

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

function partialUsingArguments(fn) {
    let arg = [].slice.call(arguments,1);
    function result(){
        let arg2 = [].slice.call(arguments,0);
        return fn.apply(this,arg.concat(arg2))
    }
    return result;
}

引用类型

遍历属性

找出对象 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"]

题解:


//题目要求找不在原型链上的属性,即返回实例属性,有3种正确方法(按提交运行速度由快到慢排列):
//1. Object.keys 方法(156 ms)
//返回可枚举的实例属性的数组。
function iterate2(obj) {
    return Object.keys(obj).map(key=>{
        return key + ": " + obj[key];
    })
}

//2. for-in 和 hasOwnProperty 方法(171 ms)
//前者用于遍历所有属性,后者用于判断是否为实例属性。
function iterate3(obj) {
    const res = [];
    for(let i in obj){
        if(obj.hasOwnProperty(i)){
            res.push(i + ": " + obj[i]);
        }
    }
    return res;
} 
//3. Object.getOwnPropertyNames 方法(209 ms)
//用法跟1.一样,区别在于返回的是所有实例属性(包括不可枚举的)。
//题目没有说明返回的实例属性是否包括不可枚举的,这里理解为包括。否则,由于 Object.keys() 返回的仅为可枚举的实例属性,应该无法通过。
function iterate(obj) {    
    return Object.getOwnPropertyNames(obj).map(function(key) {
        return key + ": " + obj[key];
    });
}

其他

FED44 柯里化

已知 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

题解

function curryIt(fn) {   
    let n = fn.length; //fn的参数个数
    let arr = [];
    return function (arg){
        arr.push(arg);
        if(arr.length < n){
            return arguments.callee;//(其作用是引用当前正在执行的函数,这里是返回的当前匿名函数)
        }else{
            return fn.apply(this,arr);
        }
    }
}
function curryIt(fn) {  
    return function a(x1){
        return function b(x2){
            return function c(x3){
                return fn.call(this,x1,x2,x3)
            }
        }
    }
}