nk前端篇-JS能力测评js1
- JS
- JS34 **购物面板**
- JS35 **接口**
- JS36 **切换Tab栏目**
- JS37 **双向绑定**
- JS38 **高频数据类型**
- JS39 **字体高亮**
- JS40 **虚拟DOM**
- JS41 **dom 节点查找**
- JS42 **获取 url 参数**
- JS43 **修改 this 指向**
- JS44 **根据包名,在指定空间中创建对象**
- JS45 **数组去重**
- JS46 **斐波那契数列**
- JS47 **时间格式化输出**
- JS48 **获取字符串的长度**
- JS49 **邮箱字符串判断**
- JS50 **计数**
- JS51 **查找重复元素**
- JS52 **计时器**
- JS53 **流程控制**
- JS54 **函数传参**
- JS55 **函数的上下文**
- JS56 **返回函数**
- JS57 **使用闭包**
- JS58 **二次封装函数**
- JS59 **使用 arguments**
- JS60 **使用 apply 调用函数**
- 总结
- 更多
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)