【前端】nk前端篇-JS能力测评js(2)

JS

JS34 购物面板

请补全JavaScript代码,要求如下:
\1. 当点击"-“按钮时,商品数量减1
\2. 当点击”+"按钮时,商品数量加1
\3. 每当点击任意按钮时,购物面板中相关信息必须同步更新
注意:
\1. 必须使用DOM0级标准事件(onclick)

在这里插入图片描述

<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8>
    </head>
    <body>
    	<table>
            <thead>
                <caption>
                    商品
                </caption>
            </thead>
            <tbody>
                <tr>
                    <td>炸鸡</td>
                    <td>28元</td>
                    <td><button id="zjtaiduola" onclick="clickBtn(event,'zjsl',28)">-</button></td>
                    <td><span id="zjsl">0</span></td>
                    <td><button id="zjtaishaola" onclick="clickBtn(event,'zjsl',28)">+</button></td>
                </tr>
                <tr>
                    <td>可乐</td>
                    <td>5元</td>
                    <td><button id="kltaiduola" onclick="clickBtn(event,'klsl',5)">-</button></td>
                    <td><span id="klsl">0</span></td>
                    <td><button id="kltaishaola" onclick="clickBtn(event,'klsl',5)">+</button></td>
                </tr>
                <tr>
                    <td>总价:</td>
                    <td><span id="total">0</span></td>
                </tr>
            </tbody>
        </table>
        
        <script type="text/javascript">
            // 补全代码
            function clickBtn(e,typeId,price){
                let totalPrice = document.querySelector('#total')
                let typeNode = document.querySelector('#' + typeId)  
                let action = e.target.innerText
                if(action == '+'){
                    typeNode.innerText = +typeNode.innerText + 1
                    totalPrice.innerText = 
                        +totalPrice.innerText +  price
                }else if(typeNode.innerText != '0'){
                    totalPrice.innerText = 
                        +totalPrice.innerText - price
                    typeNode.innerText = typeNode.innerText - 1
                }
            }
        </script>
    </body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8>
    </head>
    <body>
    	<table>
            <thead>
                <caption>
                    商品
                </caption>
            </thead>
            <tbody>
                <tr>
                    <td>炸鸡</td>
                    <td>28元</td>
                    <td><button id="zjtaiduola">-</button></td>
                    <td><span id="zjsl">0</span></td>
                    <td><button id="zjtaishaola">+</button></td>
                </tr>
                <tr>
                    <td>可乐</td>
                    <td>5元</td>
                    <td><button id="kltaiduola">-</button></td>
                    <td><span id="klsl">0</span></td>
                    <td><button id="kltaishaola">+</button></td>
                </tr>
                <tr>
                    <td>总价:</td>
                    <td><span id="total">0</span></td>
                </tr>
            </tbody>
        </table>
        
        <script type="text/javascript">
            // 补全代码
            zjplus = document.getElementById('zjtaishaola')
             zjsl = document.getElementById('zjsl')
             zjsub = document.getElementById('zjtaiduola')
              
             klplus = document.getElementById('kltaishaola')
             klsl = document.getElementById('klsl')
             klsub = document.getElementById('kltaiduola')
             
            allsum=document.getElementById('total')
            klsub.onclick =function(){
                let num=Number(klsl.innerHTML);
                let next=0
                if(num!=0) {next=num-1;
                 klsl.innerHTML=next+"";
                allsum.innerHTML=Number(allsum.innerHTML)-5
                           }
            }
            klplus.onclick=function(){
                let num=Number(klsl.innerHTML);
                let next=num+1;
                klsl.innerHTML=next+"";
                allsum.innerHTML=Number(allsum.innerHTML)+5
            }
             zjsub.onclick =function(){
                let num=Number(zjsl.innerHTML);
                let next=0
                if(num!=0){ next=num-1;
                 zjsl.innerHTML=next+"";
                 allsum.innerHTML=Number(allsum.innerHTML)-28}
            }
            zjplus.onclick=function(){
                let num=Number(zjsl.innerHTML);
                let next=num+1;
                zjsl.innerHTML=next+"";
                allsum.innerHTML=Number(allsum.innerHTML)+28
            }
        </script>
    </body>
</html>
JS35 接口

请补全JavaScript代码,完成函数的接口功能。要求如下:
\1. 函数接收两种类型的参数,分别为"get?“和"update?name=xxx&to=yyy”,“name”、"to"为参数,“xxx”、"yyy"分别为参数对应的值。
\2. 当参数为"get?“时,返回data数据
\3. 当参数为"update?name=xxx&to=yyy"时,将data中所有"name"为"xxx"的项,更改为"name"值为"yyy”

        <script type="text/javascript">
            let data = [
                {name: 'nowcoder1'},
                {name: 'nowcoder2'}
            ]
            
            const _api = string => {
                // 补全代码
                let arr = string.split('?')
                if(arr[0] === 'get'){
                    return data
                }else{
                    let b = {}
                    let a = arr[1].split('&')
                    a.forEach(item => {
                        let [key,value] = item.split('=')
                        b[key] = value
                    })
                    data.forEach((item,index) => {
                        if(item.name == b.name){
                            data[index].name = b.to
                        }
                    })
                }
            }
        </script>
JS36 切换Tab栏目

请补全JavaScript代码,实现效果如下:
\1. 当点击某个栏目(题库、面试、学习、求职)时,该栏目背景色变为’#25bb9b’,其它栏目背景色位’#fff’。
\2. 当选中某个栏目时,下方内容就展示索引值相同的类名为".items"的"li"元素
注意:
\1. 必须使用DOM0级标准事件(onclick)
\2. 已使用自定义属性存储了栏目的索引值。点击栏目获取索引值,使用索引值控制类名为"items"下的"li"元素

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <style>
            ul {
                padding: 0;
                margin: 0;
                list-style: none;
            }

            .options li {
                float: left;
                width: 100px;
                height: 40px;
                line-height: 40px;
                text-align: center;
                border: solid 1px #ddd;
            }

            .items li {
                width: 405px;
                height: 405px;
                display: none;
                border: solid 1px #ddd;
            }
        </style>
    </head>
    <body>
        <ul class='options'>
            <li data-type="0" style='background-color: #25bb9b;'>题库</li>
            <li data-type="1">面试</li>
            <li data-type="2">学习</li>
            <li data-type="3">求职</li>
        </ul>
        <ul class='items'>
            <li style="display: block;">牛客题库,包含编程题、选择题等</li>
            <li>为你的面试提供一站式服务</li>
            <li>校招学习来牛客</li>
            <li>求职中有什么难题,可以联系我们</li>
        </ul>

        <script>
            var options = document.querySelector('.options');
            var optionItems = [].slice.call(document.querySelectorAll('.options li'));
            var items = [].slice.call(document.querySelectorAll('.items li'));
            // 补全代码
            options.onclick = function(e){
                for(let i in optionItems){
                    if(e.target === optionItems[i]){
                        optionItems[i].style.backgroundColor = '#25bb9b'
                        items[i].style.display = 'block'
                    }else{
                        optionItems[i].style.backgroundColor = '#fff'
                        items[i].style.display = 'none'
                    }
                }
            }
        </script>
    </body>
</html>
JS37 双向绑定

请补全JavaScript代码,要求如下:
\1. 监听对象属性的变化
\2. 当"person"对象属性发生变化时,页面中与该属性相关的数据同步更新
\3. 将输入框中的值与"person"的"weight"属性绑定且当输入框的值发生变化时,页面中与该属性相关的数据同步更新
注意:
\1. 必须使用Object.defineProperty实现且触发set方法时更新视图
\2. 必须使用DOM0级标准事件(oninput)
\3. 可以使用预设代码"_render"函数

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <style>
            ul {
                list-style: none;
            }
        </style>
        <input type="text">
        <ul></ul>

        <script>
            var ul = document.querySelector('ul');
            var person = { sex: '男', age: '25', name: '王大锤', height: 28, weight: 32 };
            var inp = document.querySelector('input');
            inp.value = person.weight;
            const _render = () => {
                var str = `<li>姓名:<span>${person.name}</span></li>
                           <li>性别:<span>${person.sex}</span></li>
                           <li>年龄:<span>${person.age}</span></li>
                           <li>身高:<span>${person.height}</span></li>
                           <li>体重:<span>${person.weight}</span></li>`
                ul.innerHTML = str;
                inp.value = person.weight;
            }
            _render(ul);
            // 补全代码
            inp.oninput =function(e){
                person.weight = this.value;
            }
         
            Object.keys(person).forEach(key=>{
                 let value = person[key];
                 Object.defineProperty(person,key,{
                     set(newValue){
                        if(newValue != value){
                            value = newValue
                            _render(ul);
                        }
                     },
                     get(){
                         return value
                     }
                 })
            })
        </script>
    </body>
</html>
JS38 高频数据类型

请补全JavaScript代码,要求找到参数数组中出现频次最高的数据类型,并且计算出出现的次数,要求以数组的形式返回。
注意:
\1. 基本数据类型之外的任何引用数据类型皆为"object"
\2. 当多种数据类型出现频次相同时将结果拼接在返回数组中,出现次数必须在数组的最后

示例1

输入:__findMostType([0,0,’’,’’])

输出:[‘number’,‘string’,2]或[‘string’,‘number’,2]

        <script type="text/javascript">
            const _findMostType = array => {
                // 补全代码
                let o = {}
                let maxnum = 0
                let arr = []
                array.forEach(item => {
                    let type = (typeof item) ? (typeof item) : 'object'
                    o[type] = o[type] ? o[type] + 1 : 1
                    maxnum = maxnum > o[type] ? maxnum : o[type]
                })
                
                Object.keys(o).forEach(key => {
                    if(o[key] == maxnum){
                        arr.push(key)
                    }
                })
                arr.push(maxnum)
                return arr
            }
        </script>
JS39 字体高亮

请补全JavaScript代码,实现一个搜索字体高亮的效果。要求如下:
\1. 在input框中输入要搜索的内容,当点击查询按钮时,被搜索的字体样式变为加粗,背景色变为’yellow’
\2. 重新输入搜索文字,点击查询按钮时,去掉上一次的搜索效果,高亮显示效果只加在本次搜索文字上
\3. 如果搜索不到相关内容,清除之前的效果
注意:
\1. 需要加粗的文字请使用b标签包裹
\2. 必须使用DOM0级标准事件(onclick)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <input type="text">
        <button style="margin-right: 80px">查询</button>
        <div class="text" style="margin-top: 70px">
            牛客网隶属于北京牛客科技有限公司,牛客网成立于 2014 年 9 月,是以科技和创新驱动的教育科技公司。牛客网坚持以前沿技术服务于技术、以人工智能和大数据提升学习效率,专注探索在线教育创新模式,致力于为技术求职者提供能力提升解决方案,同时为企业级用户提供更高效的招聘解决方案,并为二者搭建桥梁,构建从学习到职业的良性生态圈。
    发展至今,牛客网在技术类求职备考、社群交流、企业招聘服务等多个垂直领域影响力均在行业中遥遥领先,产品矩阵包括IT题库、在线编程练习、线上课程、交流社区、竞赛平台、笔面试服务、ATS系统等,用户覆盖全国高校百万IT学习者并在高速增长中,同时也为京东、百度、腾讯、滴滴、今日头条、华为等200多家企业提供校园招聘、编程竞赛等线上服务,并收获良好口碑。
        </div>

        <script>
            var text = document.querySelector(".text");
            var search = document.querySelector("input");
            const btn = document.querySelector("button");
            btn.onclick = () => {
            // 补全代码
                let query = search.value
                let newText = text.innerText
                if (query) {
                    newText = text.innerText.replace(
                        new RegExp(query, 'g'),
                        `<b style="background-color:yellow;">${query}</b>`
                    )
                }
                text.innerHTML = newText
            }
        </script>
    </body>
</html>
JS40 虚拟DOM

请补全JavaScript代码,要求将对象参数转换为真实的DOM结构并返回。
注意:
\1. tag为标签名称、props为属性、children为子元素、text为标签内容

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

        <script>
            var vnode = {
                tag: 'ul',
                props: {
                    class: 'list'
                },
                text: '',
                children: [
                    {
                        tag: "li",
                        props: {
                            class: "item"
                        },
                        text: '',
                        children: [
                            {
                                tag: undefined,
                                props: {},
                                text: '牛客网',
                                children: []
                            }
                        ]
                    },
                    {
                        tag: "li",
                        props: {},
                        text: '',
                        children: [
                            {
                                tag: undefined,
                                props: {},
                                text: 'nowcoder',
                                children: []
                            }
                        ]
                    }
                ]
            }
            const _createElm = function(vnode) {
                // 补全代码
                let node=document.createElement(vnode.tag);
                for (const key in vnode.props) {
                  node.setAttribute(key,vnode.props[key])
                }
                node.innerText=vnode.text;
                for (let child of vnode.children) {
                  node.appendChild( arguments.callee(child))
                }
                return node;
            }
        </script>
    </body>
</html>
JS41 dom 节点查找

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

输入描述:

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

function commonParentNode(oNode1, oNode2) {
    if(oNode1.contains(oNode2)){
        return oNode1
    }else{
        return commonParentNode(oNode1.parentNode, oNode2)
    }
}
function commonParentNode(oNode1, oNode2) {
    while(true){
        oNode1 = oNode1.parentNode;
        if(oNode1.contains(oNode2)){
            return oNode1;
        }
    }
}
JS42 获取 url 参数

获取 url 中的参数
\1. 指定参数名称,返回该参数的值 或者 空字符串
\2. 不指定参数名称,返回全部的参数对象 或者 {}

\3. 如果存在多个同名参数,则返回数组

\4. 不支持URLSearchParams方法

示例1

输入:

http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key

输出:[1, 2, 3]

function getUrlParam(sUrl, sKey) {
    //解析URL,获取参数
    var keyArr = sUrl.split('?')[1].split('#')[0].split('&')
    
    var keyObj = {}
    for(var item of keyArr){
        var [i, j] = item.split('=')
        //判断是否已经拥有的属性
        if(keyObj[i] === void 0){
            keyObj[i] = j  
        }else{
            keyObj[i] = [].concat(keyObj[i], j)
        }
    }
    return sKey === void 0 ? keyObj : keyObj[sKey] || ''
    
}
JS43 修改 this 指向

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

call()、bind()、apply()的用法,改变this的指向:
f.call(obj, arg1, arg2...),
f.bind(obj, arg1, arg2,...)(),
f.apply(obj, [arg1, arg2, .])

call

function bindThis(f, oTarget) {
 return function() {
     return f.call(oTarget, ...arguments)
 }
}

bind

function bindThis(f, oTarget) {
 return f.bind(oTarget)
}

apply

function bindThis(f, oTarget) {
 return function() {
     return f.apply(oTarget, arguments)
 }
}
JS44 根据包名,在指定空间中创建对象

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

输入描述:

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

输出描述:

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

	首先要排除掉原型链上的属性,判断对象自身有没有这个属性,然后再严格判断属性值是否为对象。
	而包名字符串是简单顺序的,所以可以直接 split 出来遍历,利用引用赋值的特性逐级跟进到包里面:
function namespace(oNamespace, sPackage) {
    let list = sPackage.split('.');
    let tmp = oNamespace;
    for(let k in list){
        if(typeof tmp[list[k]] !== 'object'){
            tmp[list[k]] = {};
        }
        tmp = tmp[list[k]];
    }
    return oNamespace;
}
JS45 数组去重

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

示例1

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

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

Array.prototype.uniq = function () {
    return Array.from(new Set(this))
}
Array.prototype.uniq = function () {
    return [...new Set(this)];
}
JS46 斐波那契数列

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

function fibonacci(n) {
    if(n < 1)    return -1;
    let a = 1,b = 1;
    for(let i = 2;i < n;i++){
        b = a + b;
        a = b - a;
    }
    return b;
}
JS47 时间格式化输出

按所给的时间格式输出指定的时间
格式说明
对于 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 结果为 五

示例1

输入:formatDate(new Date(1409894060000), ‘yyyy-MM-dd HH:mm:ss 星期w’)

输出:2014-09-05 13:14:20 星期五

function formatDate(t,str){
    let obj = {
        yyyy:t.getFullYear(),
        yy:("" + t.getFullYear()).slice(-2),
        M:t.getMonth() + 1,
        MM:("0" + (t.getMonth() + 1)).slice(-2),
        d:t.getDate(),
        dd:("0" + t.getDate()).slice(-2),
        H:t.getHours(),
        HH:("0" + t.getHours()).slice(-2),
        h:t.getHours() % 12,
        hh:("0" + t.getHours() % 12).slice(-2),
        m:t.getMinutes(),
        mm:("0" + t.getMinutes()).slice(-2),
        s:t.getSeconds(),
        ss:("0" + t.getSeconds()).slice(-2),
        w:['日','一','二','三','四','五','六'][t.getDay()]
    };
    return str.replace(/([a-z]+)/ig,function($1){return obj[$1]});
}
JS48 获取字符串的长度

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

示例1

输入:‘hello world, 牛客’, false

输出:17

function strLength(s, bUnicode255For1) {
    let len = s.length;
    if(bUnicode255For1 == true){
        return len;
    }else{
        for(let i in s){
            if(s.charCodeAt(i) > 255)
                len++;
        }
    }
    return len;
}
JS49 邮箱字符串判断

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

输入描述:邮箱字符串

输出描述:true表示格式正确

function isAvailableEmail(sEmail) {
    let reg = /^([\w+\.])+@\w+([.]\w+)+$/;
    return reg.test(sEmail);
}
 /^([\w+\.])+@\w+([.]\w+)+$/;
([\w+\.])+:等同于[a-zA-Z0-9_\.],也就是a-zA-Z0-9_.任意其中一个;
@: 匹配到@;
\w+: 一个或多个[a-zA-Z0-9_];
([.]\w+)+: 以点开头的,后跟一个或多个[a-zA-Z0-9_];
$: 结束符.
JS50 计数

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

示例1

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

输出:3

function count(arr, item) {
    let num = 0;
    arr.forEach(function(a){
        if(a == item){
            num++;
        }
    });
    return num;
}
JS51 查找重复元素

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

示例1

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

输出:[1, 3, 4]

function duplicates(arr) {
    let res = []
    arr.forEach(function(item){
        if(arr.indexOf(item) != arr.lastIndexOf(item) && res.indexOf(item) == -1){
            res.push(item)
        }
    })
    return res
}
JS52 计时器

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

立即输出第一个值;返回一个对象;
//setInterval()
function count(start, end) {
    console.log(start++);
    let timer = setInterval(function(){
        if(start <= end){
            console.log(start++)
        }else{
            clearInterval(timer)
        }
    },100)
    return {
        cancel:function(){
                clearInterval(timer);
        }
    }
}
//setTimeout
function count(start, end) {
    if(start <= end){
        console.log(start++);
        item = setTimeout(function(){count(start,end)},100);
    }
    return{
        cancel:function(){clearTimeout(item);}
    }
}
JS53 流程控制

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

示例1

输入:15

输出:fizzbuzz

function fizzBuzz(num) {
    if(num == null || typeof(num) != 'number'){
        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;
    }
}
JS54 函数传参

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

示例1

输入:

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

输出:

Hello, Ellie!
function argsAsArray(fn, arr) {
    return fn(arr[0],arr[1],arr[2]);
}
function argsAsArray(fn, arr) {
    return fn(...arr);
}
function argsAsArray(fn, arr) {
    return fn.apply(fn,arr);
}
//apply :第一个参数:函数体内this的指向,第二个参数:接收一个集合对象(数组和类数组)
JS55 函数的上下文

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

示例1

输入:

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

输出:

Hello, Rebecca!!!
function speak(fn, obj) {
    return fn.call(obj)
}

方法一:直接将fn挂载到obj对象上(把fn的方法放到
obj上执行)

function speak(fn, obj) {
    obj.fn = fn
    return obj.fn()
}

方法二:使用apply

在JavaScript中,函数是一种对象,其上下文是可以变化的,对应的,函数内的this也是可以变化的,函数可以作为一个对象的方法,也可以同时作为另一个对象的方法,可以通过Function对象中的call或者apply方法来修改函数的上下文,函数中的this指针将被替换为call或者apply的第一个参数。将函数 fn 的执行上下文改为 obj 对象,只需要将obj作为call或者apply的第一个参数传入即可。

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

方法三:使用call

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

方法四:使用bind

function speak(fn, obj) {
    return fn.bind(obj)()
}
JS56 返回函数

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

示例1

输入:functionFunction(‘Hello’)(‘world’)

输出:Hello, world

function functionFunction(str) {
    let fun = function(s){
        return str + ", " + s;
    }
    return fun;
}
JS57 使用闭包

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

示例1

输入:

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

输出:

4

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。

典型方法:

function makeClosures(arr, fn) {
    var result = [];
    for(var i = 0;i < arr.length;i++){
        result[i] = function(ele){
            return function(){
                return fn(ele);
            }
        }(arr[i]);
    }
    return result;
}

es6方法:

function makeClosures(arr, fn) {
    let result = [];
    for(let i = 0;i < arr.length;i++){
        result[i] = function(){
            return fn(arr[i]);//es6语法可以用,避免闭包问题
        };
    }
    return result;
}
//这样不对:这样在函数内部又创建了一个函数,形成了闭包,导致result中每个函数的参数都是arr[arr.length]。
//先执行for循环的内容,最后才执行匿名函数的内容,结果为NaN.
//function makeClosures(arr, fn) {
//    let result = [];
//    for(var i = 0;i < arr.length;i++){
//        result[i] = function(){
//            return fn(arr[i]);
//        };
//    }
//    return result;
//}

forEach:

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

使用ES5的bind()方法:

function makeClosures(arr, fn) {
    var result = new Array();
    for(var i=0;i<arr.length;i++){
        result[i] = fn.bind(null,arr[i]);
    }
    return result;
}
JS58 二次封装函数

已知函数 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!!!

``

//ES6,this指向undefined
// call和apply必须显式地调用str3,立即执行
// bind不是立即执行,未传入str3时,并未执行,只是返回一个函数,等待参数传入
// this用于上下文不确定的情况
//匿名函数默认this绑定global,与bind的第一个参数为this时效果一样。
``

ES6

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

call、apply

function partial(fn, str1, str2) {
    function result(str3) {
        return fn.call(this, str1, str2, str3);
    }
    return result;
}

bind

//str1与str2已定,等待传入str3执行
function partial(fn, str1, str2) {
    return fn.bind(this, str1, str2);
}

//多了一步,把str3传入的过程写在另一个函数里,此法有种多次一举的感觉,但是表示出了后续的调用。
function partial(fn, str1, str2) {
    function result(str3) {
        return fn.bind(this, str1, str2)(str3);
    }
    return result;
}

匿名函数

//默认this绑定global,与bind的第一个参数为this时效果一样。
function partial(fn, str1, str2) {
    let fun = function(str){
        return fn(str1,str2,str);
    }
    return fun;
}
JS59 使用 arguments

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

示例1

输入:1, 2, 3, 4

输出:10

``

arguments能获得函数对象传入的参数组,类似于一个数组,能够通过length获取参数个数,能通过下标获取该位置的参数,但是它不能使用forEach等方法。
``

function useArguments() {
    let num = 0;
    for(let i = 0;i < arguments.length;i++){
        num += arguments[i];
    }
    return num;
}
JS60 使用 apply 调用函数

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

示例1

输入:无

输出:无

``

arguments并非真正的数组,因此要获得callIt的第一个参数之后的所有参数,不能直接使用slice方法截取,需要先将arguments转换为真正的数组。
两种常见的方法.二是循环遍历逐一填入新数组。在获得了args之后,就可以调用apply来执行传入的函数参数。
``

1、使用slice方法

function callIt(fn) {
    var result = Array.prototype.slice.call(arguments);
    return fn.apply(null,result);
}
function callIt(fn) {
 return fn.apply(this,[].slice.call(arguments,1))
}

2、遍历

function callIt(fn) {
  var arr=[];
  for(var i=1;i<arguments.length;i++){
    arr.push(arguments[i]);
  }
  return fn.apply(callIt,arr);
}

总结

这里对文章进行总结:
以上就是nk前端篇-JS能力测评js的第二部分内容,本文介绍了js相关的一些使用方法,在此记录,更多关于前端题目会后续继续整理。

更多

【前端】nk前端篇-零基础FED
【前端】nk前端篇-CSS布局CSS
【前端】nk前端篇-JS能力测评js(1)
【前端】nk前端篇-JS能力测评js(2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值