很快,又要到了秋招时刻,说实话校招刷题还是很重要的。牛客网这个前端笔试题库 ,可以说这75题中的前60题道是前端最基础的了,也是考察的东西比较杂,后面的15题更侧重实战,对于巩固基础还是有帮助的的。做完题回顾一上午就可以过完一遍。现在我结合我的答案和参考的其他人的答案,在这里做一个总结,方便自己以后复习,也帮后来人少走点弯路。
问题描述 封装函数 f,使 f 的 this 指向指定的对象。
这里给出三种写法,哪种都可以。
apply修改this作用域 1 2 3 4 5 function bindThis (f, oTarget ) { return function ( ) { return f.apply(oTarget, arguments ); } }
call修改this作用域 1 2 3 4 5 function bindThis (f, oTarget ) { return function ( ) { return f.call(oTarget, ...arguments); } }
bind修改this作用域 注意需要调用函数,bind默认绑定this懒执行
1 2 3 4 5 function bindThis (f, oTarget ) { return function ( ) { return f.bind(oTarget, ...arguments)(); } }
或者直接简写
1 2 3 function bindThis (f, oTarget ) { return f.bind(oTarget); }
相关知识点
apply、call、bind的作用都是修改执行上下文 apply、call都是返回函数立即执行的结果,其中apply第二个参数之后是数组,call第二个参数之后是单个的值。 bind返回的是函数,需要手动执行结果。第二个参数之后是单个的值。
问题描述 获取 url 中的参数
指定参数名称,返回该参数的值 或者 空字符串
不指定参数名称,返回全部的参数对象 或者 {}
如果存在多个同名参数,则返回数组
输入:http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key
输出:[1, 2, 3]
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 function getUrlParam (sUrl, sKey ) { let sParam = sUrl.split("?" )[1 ].split("#" )[0 ]; let arr = sParam.split("&" ); let res; if ( sKey ){ res = []; for (let i = 0 ; i < arr.length; i++) { let temp = arr[i].split("=" ); if (temp[0 ] === sKey){ res.push(temp[1 ]); } } if (res.length === 1 ) { return res[0 ]; } else if (res.length === 0 ){ return "" ; } else { return res; } } else { res = {}; if (sParam === undefined || sParam === "" ){ return res; } for (let i = 0 ; i < arr.length; i++) { let temp = arr[i].split("=" ); if (!(temp[0 ] in res)){ res[temp[0 ]] = []; } res[temp[0 ]].push(temp[1 ]); } } return res; }
大同小异的做法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 function getUrlParam (sUrl, sKey ) { let newArr = []; let newObj = {}; let query = sUrl.split("#" )[0 ].split("?" )[1 ]; if (query) { let arr = query.split("&" ); for (let i = 0 ; i < arr.length; i++) { if (arr[i]) { arr[i] = arr[i].split("=" ); if (sKey !== undefined ) { if (arr[i][0 ] === sKey) { newArr.push(arr[i][1 ]); } } else { if (arr[i][0 ] in newObj) { newObj[arr[i][0 ]].push(arr[i][1 ]); } else { newObj[arr[i][0 ]] = [arr[i][1 ]]; } } } } if (sKey !== undefined ) { switch (newArr.length) { case 0 : return "" ; break ; case 1 : return newArr[0 ]; break ; default : return newArr; break ; } } else { return newObj; } } else { return sKey !== undefined ? {} : "" ; } }
相关知识点
url的组成部分
https://user:pass@www.baidu.com:80/index.html?type=1&name=2#hahahttp/https 是协议user:pass@ 是登录认证www.baidu.com 是域名,服务器地址:80 是端口号/index.html 是请求资源文件路径?type=1&name=2 是查询字符串,携带参数,给服务器传的内容。#haha 是哈希,片段标识符
split方法
字符串分割成数组的方法,里面的参数是以什么分割,如果不传就是空字符串为分割,返回值是一个数组。
query部分可以使用正则
问题描述 查找两个节点的最近的一个共同父节点,可以包括节点自身
输入描述: oNode1 和 oNode2 在同一文档中,且不会为相同的节点
代码 1 2 3 4 5 6 7 8 9 10 function commonParentNode (oNode1, oNode2 ) { if (oNode1.contains(oNode2)) { return oNode1; } else { return commonParentNode(oNode1.parentNode, oNode2); } }
相关知识点
contains API
查看dom元素包含关系,包含返回true,不包含返回false参考MDN
递归(参考数据结构树)
问题描述 根据包名,在指定空间中创建对象 输入描述:
1 namespace({a : {test : 1 , b : 2 }}, 'a.b.c.d' )
输出描述:
1 {a : {test : 1 , b : {c : {d : {}}}}}
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function namespace (oNamespace, sPackage ) { let arr = sPackage.split('.' ); let pointer = oNamespace; for (let i = 0 ; i < arr.length; i++) { if (!pointer[arr[i]] || typeof pointer[arr[i]] !== 'object' ) { pointer[arr[i]] = {}; } pointer = pointer[arr[i]]; } return oNamespace; }
代码写的更加严谨一点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function namespace (oNamespace, sPackage ) { let arr = sPackage.split('.' ); let pointer = oNamespace; for (let i = 0 ; i < arr.length; i++) { if (!pointer.hasOwnProperty(arr[i]) || Object .prototype.toString.call(pointer[arr[i]]) !== '[object Object]' ) { pointer[arr[i]] = {}; } pointer = pointer[arr[i]]; } return oNamespace; }
相关知识点
问题描述 为 Array 对象添加一个去除重复项的方法 输入:
1 [false , true , undefined , null , NaN , 0 , 1 , {}, {}, 'a' , 'a' , NaN ]
输出:
1 [false , true , undefined , null , NaN , 0 , 1 , {}, {}, 'a' ]
这个题,狗就狗在,还有NaN,所以要参考数组去重 中的能去掉NaN的方法
利用includes去重 1 2 3 4 5 6 7 8 9 Array .prototype.uniq = function ( ) { let res = []; for (let i = 0 ; i < this .length; i++) { if (!res.includes(this [i])) { res.push(this [i]); } } return res; }
利用ES6 Set去重 1 2 3 Array .prototype.uniq = function ( ) { return [...new Set (this )]; }
普通双重循环加NaN标志位 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Array .prototype.uniq = function ( ) { let arr = []; let flag = true ; this .forEach((value ) => { if (arr.indexOf(value) === -1 ) { if (value !== value) { if (flag) { arr.push(value); flag = false ; } } else { arr.push(value); } } }); return arr; };
相关知识点
uniq方法中的this指向哪里?
Array构造函数的原型方法中的this指的是数组实例。
Set的特性
Set存储的成员是唯一的,不是重复的,如果有重复会自动过滤掉.ES6(七)—— Set & Map
(NaN === NaN) => false
NaN : is not a number,不等于自己 typeof NaN => number Object.prototype.toString.call(NaN) => “[object Number]” ES6 新增方法:Number.isNaN() 用来判断是否属于数字
题目描述 用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等
斐波那契数列基本学js都会,1 1 2 3 5 8 13,后一个是前两个的和。
递归 1 2 3 4 5 function fibonacci (n ) { if (n === 0 ) return 0 ; if (n === 1 || n === 2 ) return 1 ; return fibonacci(n - 1 ) + fibonacci(n - 2 ); }
动态规划 1 2 3 4 5 6 7 8 9 10 11 12 13 function fibonacci (n ) { if (n < 2 ) return n; let dp0 = 0 , dp1 = 1 ; for (let i = 2 ; i <= n; i++) { let temp = dp0 + dp1; dp0 = dp1; dp1 = temp; } return dp1; }
特征方程 1 2 3 4 5 function fibonacci (n ) { const sqrt5 = Math .sqrt(5 ); const fibN = Math .pow((1 + sqrt5) / 2 , n) - Math .pow((1 - sqrt5) / 2 , n); return Math .round(fibN / sqrt5); }
相关知识点
题目描述 按所给的时间格式输出指定的时间 格式说明 对于 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' )
输出:
使用replace函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 function formatDate (t, str ) { let year = "" + t.getFullYear(); let month = t.getMonth() + 1 ; let day = t.getDate(); let hour = t.getHours(); let minutes = t.getMinutes(); let second = t.getSeconds(); let week = ["日" , "一" , "二" , "三" , "四" , "五" , "六" ]; let date = { yyyy: year, yy: year.slice(2 ), MM: ten(month), M: month, dd: ten(day), d: day, HH: ten(hour), H: hour, hh: ten(hour % 12 ), h: hour % 12 , mm: ten(minutes), m: minutes, ss: ten(second), s: second, w: week[t.getDay()], }; for (let key in date) { str = str.replace(key, date[key]); } return str; } let ten = (num ) => (num >= 10 ? num : "0" + num);
使用正则表达式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 function formatDate (t, str ) { let obj = { yyyy: t.getFullYear(), yy: ("" + t.getFullYear()).slice(-2 ), MM: ("0" + (t.getMonth() + 1 )).slice(-2 ), M: t.getMonth() + 1 , dd: ("0" + t.getDate()).slice(-2 ), d: t.getDate(), HH: ("0" + t.getHours()).slice(-2 ), H: t.getHours(), hh: ("0" + (t.getHours() % 12 )).slice(-2 ), h: t.getHours() % 12 , mm: ("0" + t.getMinutes()).slice(-2 ), m: t.getMinutes(), ss: ("0" + t.getSeconds()).slice(-2 ), s: t.getSeconds(), w: ["日" , "一" , "二" , "三" , "四" , "五" , "六" ][t.getDay()], }; return str.replace(/([a-z]+)/gi , function ($1 ) { return obj[$1 ]; }); }
相关知识点
获取年月日周时分秒的系统API
格式统一处理
字符串替换 (replace)
题目描述 如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1 否则如果字符 Unicode 编码 > 255 则长度为 2 输入:
输出:
代码 1 2 3 4 5 6 7 8 function strLength (s, bUnicode255For1 ) { let len = s.length; if (bUnicode255For1) return len; for (let i = 0 ; i < s.length; i++) { if (s[i].charCodeAt() > 255 ) len++; } return len; }
相关知识点
获取字符的 Unicode 编码 API —— str.charCodeAt()
题目描述 判断输入是否是正确的邮箱格式
考察正则的一道题目,方法也是多种多样,这里只有一种简单的参考。
1 2 3 4 5 6 7 8 9 function isAvailableEmail (sEmail ) { return /^([\w+\.])+@\w+([\.]\w+)+$/ .test(sEmail); }
相关知识点
题目描述 将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff
rgb 中每个 , 后面的空格数量不固定
十六进制表达式使用六位小写字母
如果输入不符合 rgb 格式,返回原始输入
输入 :’rgb(255, 255, 255)’ 输出 :#ffffff
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function rgb2hex (sRGB ) { let regexp = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/ ; let reg = sRGB.match(regexp); if (!reg || reg.length !== 4 ) return sRGB; let str = "#" ; for (let i = 1 ; i < 4 ; i++) { let s = parseInt (reg[i]); if (s >= 0 && s <= 255 ) { str += (s < 16 ? '0' + s.toString(16 ) : s.toString(16 )); } else { return sRGB; } } return str; }
相关知识点
toString的进制转换
颜色是16进制,所以toString(16)可以得到结果
字符串中如何截取数字(不限于正则)
注意:一定要理解之后去程序里面运行一遍。
题目描述 css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能
以 - 为分隔符,将第二个起的非空单词首字母转为大写
-webkit-border-image 转换后的结果为 webkitBorderImage 输入 : ‘font-size’ 输出 : fontSize
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function cssStyle2DomStyle (sName ) { let arr = sName.split("" ); if (arr.indexOf("-" ) === 0 ) { arr.splice(0 , 1 ); } for (let i = 0 ; i < arr.length; i++) { if (arr[i] == "-" ) { arr.splice(i, 1 ); arr[i] = arr[i].toUpperCase(); } } return arr.join("" ); }
相关知识点
数组常用方法
split/join
toUpperCase() —— toUpperCase将小写字符转成大写,toLowerCase将大写字符转成小写
slice
题目描述 统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率
不限制 key 的顺序
输入的字符串参数不会为空
忽略空白字
输入 :
输出 :
1 {h : 1 , e : 1 , l : 3 , o : 2 , w : 1 , r : 1 , d : 1 }
代码 1 2 3 4 5 6 7 8 9 10 11 function count (str ) { let count = {}; for (const char of str) { if (char !== " " ) { count[char] = count.hasOwnProperty(char) ? count[char] + 1 : 1 ; } } return count; }
相关知识点
题目描述 使用一个标签将“牛客网”三个字加粗显示
html 1 <p > <strong > 牛客网</strong > ,程序员必备求职神器</p >
js 1 2 3 let p = document .getElementByTagName('p' );let text = p.innterHTML;p.innterHTML = text.replace('牛客网' ,'<strong>牛客网</strong>' );
相关知识点
题目描述 请将下面这句话以段落的形式展示在浏览器中——“牛客网是一个专注于程序员的学习和成长的专业平台。”
html 1 <p > 牛客网是一个专注于程序员的学习和成长的专业平台。</p >
js 1 2 3 let p = document .createElement('p' );p.innerHTML = '牛客网是一个专注于程序员的学习和成长的专业平台。' ; document .querySelector('body' ).append(p);
相关知识点:
创建标签createElement
将元素添加到body中 append()
题目描述 请使用嵌入样式将所有p标签设置为红色文字
行内样式 1 2 3 4 <p style ="color:red" > 欢迎来到牛客网</p > <p style ="color:red" > 在这里,我们为你提供了IT名企的笔试面试题库</p > <p style ="color:red" > 在这里,我们以题会友</p > <p style ="color:red" > QQ群号:272820159</p >
css样式 1 2 3 4 5 6 7 8 9 <style> p { color : red; } </style> <p >欢迎来到牛客网</p > <p >在这里,我们为你提供了IT名企的笔试面试题库</p > <p >在这里,我们以题会友</p > <p >QQ群号:272820159 </p >
js 1 2 3 4 let p = document .querySelectorAll('p' );for (let i = 0 ; i < p.length; i++) { p[i].style.color = 'red' ; }
相关知识点
获取所有p元素:querySelectorAll
给元素设置style样式:dom.style.color
题目描述 找出元素 item 在给定数组 arr 中的位置 输出描述: 如果数组中存在 item,则返回元素在数组中的位置,否则返回 -1 输入:
输出:
简单遍历 1 2 3 4 5 6 function indexOf (arr, item ) { for (let i = 0 ; i < arr.length; i++) { if (arr[i] == item) return i; } return -1 ; }
ES6新增数组方法 1 2 3 function indexOf (arr, item ) { return arr.findIndex(val => val === item); }
或者直接
1 2 3 function indexOf (arr, item ) { return arr.indexOf(item); }
相关知识点
题目描述 计算给定数组 arr 中所有元素的总和 输入描述: 数组中的元素均为 Number 类型 输入 :
输出 :
使用for循环遍历 1 2 3 4 5 6 7 function sum (arr ) { let count = 0 ; for (const num of arr) { count += num; } return count; }
forEach 1 2 3 4 5 6 7 function sum (arr ) { let count = 0 ; arr.forEach(num => { count += num; }) return count; }
reduce 1 2 3 function sum (arr ) { return arr.reduce((preSum, num ) => num + preSum); }
相关知识点
题目描述 移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组 输入 :
输出 :
简单遍历 1 2 3 4 5 6 7 function remove (arr, item ) { let res = []; arr.forEach(it => { if (it !== item) res.push(it); }); return res; }
filter过滤方法 1 2 3 function remove (arr, item ) { return arr.filter(it => it !== item); }
新数组中使用splice删除 1 2 3 4 5 6 7 function remove (arr, item ) { let newArr = arr.slice(0 ); for (let i = newArr.length - 1 ; i >= 0 ; i--) { if (newArr[i] === item) newArr.splice(i, 1 ); } return newArr; }
相关知识点
数组方法哪些是在原数组中改的,哪些是返回新数组的?
返回新数组的API slice \ map \ filter \ reduce \ concat … 返回原数组的API push \ unshift \ shift \ pop \ splice \ sort \ reverse …
题目描述 移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回 输入:
1 [1 , 2 , 2 , 3 , 4 , 2 , 2 ], 2
输出:
正序遍历 1 2 3 4 5 6 7 8 9 function removeWithoutCopy (arr, item ) { for (let i = 0 ; i < arr.length; i++) { if (arr[i] === item) { arr.splice(i, 1 ); i--; } } return arr; }
倒序遍历 这样不用考虑数组长度
1 2 3 4 5 6 7 function removeWithoutCopy (arr, item ) { for (let i = arr.length - 1 ; i >= 0 ; i--) { if (item === arr[i]) arr.splice(i, 1 ); } return arr; }
相关知识点
题目描述 在数组 arr 末尾添加元素 item。不要直接修改数组 arr,结果返回新的数组 输入:
输出:
简单迭代 1 2 3 4 5 6 function append (arr, item ) { let newArr = []; arr.forEach(val => newArr.push(val)); newArr.push(item); return newArr; }
slice 1 2 3 4 5 function insert (arr, item ) { let newArr = arr.slice(0 ); newArr.push(item); return newArr; }
concat 1 2 3 function append (arr, item ) { return arr.concat(item); }
ES6展开运算符 1 2 3 function append (arr, item ) { return [...arr, item]; }
相关知识点
这次好多的方法都是数组方法,所以一定要非常的熟悉。这里再把数组的方法整理放上来。 Javascript常用的数组方法
题目描述 删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组 输入:
输出:
一些简单方法就不写了,比如用循环一个一个复制除最后一个元素外的元素
slice 1 2 3 function truncate (arr ) { return arr.slice(0 , -1 ); }
返回新数组API + pop() 1 2 3 4 5 function truncate (arr ) { let newArr = [].concat(arr); newArr.pop(); return newArr; }
相关知识点
题目描述 在数组 arr 开头添加元素 item。不要直接修改数组 arr,结果返回新的数组 输入:
输出:
先把需要插入的树放进去,然后遍历数组 1 2 3 4 5 6 7 function prepend (arr, item ) { let newArr = [item]; for (let i = 0 ; i < arr.length ; i++) { newArr.push(arr[i]); } return newArr; }
unshift或者slice 1 2 3 4 5 function prepend (arr, item ) { let newArr = arr.slice(0 ); newArr.splice(0 , 0 , item); return newArr; }
concat 1 2 3 function prepend (arr, item ) { return [item].concat(arr); }
相关知识点
题目描述 删除数组 arr 第一个元素。不要直接修改数组 arr,结果返回新的数组 输入:
输出:
for循环push元素 1 2 3 4 5 6 7 function curtail (arr ) { let newArr = []; for (let i = 1 ; i < arr.length ; i++) { newArr.push(arr[i]); } return newArr; }
copy原数组,删除元素返回 1 2 3 4 5 function curtail (arr ) { let newArr = arr.slice(0 ); newArr.shift(); return newArr; }
slice 1 2 3 function curtail (arr ) { return arr.slice(1 ); }
相关知识点
题目描述 合并数组 arr1 和数组 arr2。不要直接修改数组 arr,结果返回新的数组 输入:
1 [1 , 2 , 3 , 4 ], ['a' , 'b' , 'c' , 1 ]
输出:
1 [1 , 2 , 3 , 4 , 'a' , 'b' , 'c' , 1 ]
迭代 1 2 3 4 5 6 7 function concat (arr1, arr2 ) { let newArr = arr1.slice(0 ); for (let i = 0 ; i < arr2.length; i++){ newArr.push(arr2[i]); } return newArr; }
concat 1 2 3 function concat (arr1, arr2 ) { return arr1.concat(arr2); }
ES展开运算符 1 2 3 function concat (arr1, arr2 ) { return [...arr1, ...arr2]; }
相关知识点
题目描述 在数组 arr 的 index 处添加元素 item。不要直接修改数组 arr,结果返回新的数组 输入:
输出:
普通迭代 1 2 3 4 5 6 7 8 9 10 11 12 function insert (arr, item, index ) { let newArr = []; for (let i = 0 ;i < arr.length; i++) { if (i === index) { newArr.push(item); newArr.push(arr[i]); } else { newArr.push(arr[i]); } } return newArr; }
新数组+splice方法 1 2 3 4 5 function insert (arr, item, index ) { let newArr = [...arr]; newArr.splice(index, 0 , item); return newArr; }
拼数组 1 2 3 4 function insert (arr, item, index ) { return arr.slice(0 , index).concat(item, arr.slice(index)); }
相关知识点
题目描述 统计数组 arr 中值等于 item 的元素出现的次数 输入:
1 [1 , 2 , 4 , 4 , 3 , 4 , 3 ], 4
输出:
计数器 1 2 3 4 5 6 7 function count (arr, item ) { let count = 0 ; arr.forEach(value => { if (value === item) count++; }) return count; }
filter过滤 1 2 3 4 function count (arr, item ) { let newArr = arr.filter(val => val === item); return newArr.length; }
reduce 1 2 3 4 5 function count (arr, item ) { return arr.reduce((prev, val ) => { return val === item ? ++prev : prev; }, 0 ); }
相关知识点
题目描述 找出数组 arr 中重复出现过的元素 输入:
1 [1 , 2 , 4 , 4 , 3 , 3 , 1 , 5 , 3 ]
输出:
排序+双指针 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function duplicates (arr ) { if (arr.length < 2 ) return arr; let newArr = arr.slice(0 ).sort(); let result = []; let i = 0 ; let j = 1 ; while (j < newArr.length) { if (newArr[i] === newArr[j]) { if (!result.includes(newArr[i])) result.push(newArr[i]); } else { i = j; } j++; } return result; }
使用两个Set存储 1 2 3 4 5 6 7 8 9 10 11 12 function duplicates (arr ) { let hash = new Set (); let res = new Set (); for (let i = 0 ; i < arr.length; i++) { if (hash.has(arr[i])) { res.add(arr[i]); } else { hash.add(arr[i]); } } return [...res]; }
使用map记录count 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function duplicates (arr ) { let map = new Map (); arr.forEach((value ) => { if (map.has(value)) { let count = map.get(value); map.set(value, ++count); } else { map.set(value, 1 ); } }); let res = []; for (let [key, value] of map) { if (value > 1 ) res.push(key); } return res; }
利用indexOf 1 2 3 4 5 6 7 8 9 10 11 function duplicates (arr ) { let newArr = []; arr.forEach((value ) => { if ( arr.indexOf(value) !== arr.lastIndexOf(value) && newArr.indexOf(value) === -1 ) newArr.push(value); }); return newArr; }
相关知识点
题目描述 为数组 arr 中的每个元素求二次方。不要直接修改数组 arr,结果返回新的数组 输入:
输出:
题设,就是为map准备的,牛客不太支持ES6以上的语法,目前不支持提示 ,不过正常是可以用的。
map 1 2 3 function square (arr ) { return arr.map((item ) => item * item); }
forEach 如何用forEach实现map,就采用类似的写法
1 2 3 4 5 6 7 function square (arr ) { let newArr = []; arr.forEach((value ) => { newArr.push(value * value); }); return newArr; }
相关知识点
题目描述 在数组 arr 中,查找值与 item 相等的元素出现的所有位置 输入:
1 ['a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'a' ,'b' ,'c' ] 'a'
输出:
forEach遍历 其他的遍历都大同小异,一定是要遍历就对了。
1 2 3 4 5 6 7 function findAllOccurrences (arr, target ) { let res = []; arr.forEach(function (item, index ) { if (item === target) res.push(index); }); return res; }
相关知识点
题目描述 给定的 js 代码中存在全局变量,请修复
1 2 3 4 5 6 7 function globals ( ) { myObject = { name : 'Jory' }; return myObject; }
myObject前面加var/let/const 1 2 3 4 5 6 7 function globals ( ) { let myObject = { name : 'Jory' }; return myObject; }
相关知识点
不加声明的是全局变量,容易引起全局污染。作用域分为全局作用域、函数作用域,ES6新增了块级作用域。
题目描述 请修复给定的 js 代码中,函数定义存在的问题 输入:
输出:
原代码
1 2 3 4 5 6 7 8 9 10 11 12 function functions (flag ) { if (flag) { function getValue ( ) { return "a" ; } } else { function getValue ( ) { return "b" ; } } return getValue(); }
使用函数表达式 1 2 3 4 5 6 7 8 9 10 11 12 13 function functions (flag ) { if (flag) { var getValue = () => { return "a" ; }; } else { var getValue = () => { return "b" ; }; } return getValue(); }
变量提升 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function functions (flag ) { var getValue; if (flag) { getValue = () => { return "a" ; }; } else { getValue = () => { return "b" ; }; } return getValue(); }
相关知识点
函数声明式:函数声明在函数没有执行之前就已经在作用域中会提升,同名的声明会进行覆盖,以下面的为准,那么程序执行的时候一直输出的就是b。
函数表达式:使用函数表达式,还是会进行变量的提升,只不过这次提升的是变量getValue,在执行的时候,才会根据if语句的流程控制执行不同的函数。
题目描述 修改 js 代码中 parseInt 的调用方式,使之通过全部测试用例 输入:’12’ 输出:12 输入: ‘12px’ 输出:12 输入: ‘0x12’ 输出:0
确定是十进制 1 2 3 function parse2Int (num ) { return parseInt (num, 10 ); }
相关知识点
parseInt经常用于强制类型转换中显式转换成数字,接收两个参数,返回数值或者NaN
parseInt(string, radix) 第一个参数是字符串,必须传的。 第二个参数是数字的基数,2-36,如果不传或者传0都是以10位基数来计算,如果小于2(不等于0)或者大于36一律返回NaN,如果’0x’开头为16进制,’0’开头不包括0是8进制。
parseInt强制类型转化的时候,如果第一位不是数字就会返回NaN,如果第一位是数字,那么会把后面是数字的返回,不是数字的过滤掉。如果是小数的话,会向下取整成整数。
题目描述 判断 val1 和 val2 是否完全等同
代码 1 2 3 function identity (val1, val2 ) { return val1 === val2; }
相关知识点
== 和 === 的区别,简单来说在于,== 只判断值相同,遇到问题,=== 还要判断类型是否相同。 这里其实我觉得还需要考虑NaN的问题,NaN !== NaN
题目描述 实现一个打点计时器,要求
从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
返回的对象中需要包含一个 cancel 方法,用于停止定时操作
第一个数需要立即输出
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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); } } }
相关知识点
计时器,如果第一个要立即输出,那么需要手动写一次。 定义的时候接收两个参数,第一个是每次执行的函数,第二个是执行时间间隔。 返回值接收计时器名称,可以用于清空计时器用。
题目描述 实现 fizzBuzz 函数,参数 num 与返回值的关系如下: 1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz 2、如果 num 能被 3 整除,返回字符串 fizz 3、如果 num 能被 5 整除,返回字符串 buzz 4、如果参数为空或者不是 Number 类型,返回 false 5、其余情况,返回参数 num 输入:
输出:
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 function fizzBuzz (num ) { if (isNaN (num)) return false ; 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; } }
相关知识点
isNaN(),遇到不是Number类型的判断都用这个函数,如果参数不是数字就返回true,其他的判断我觉得都不是这个题要考的。ES6之后新增了方法Number.isNaN() 判断是否是NaN
题目描述 将数组 arr 中的元素作为调用函数 fn 的参数 输入:
1 function (greeting, name, punctuation ) {return greeting + ', ' + name + (punctuation || '!' );}, ['Hello' , 'Ellie' , '!' ]
输出:
直接传参 1 2 3 function argsAsArray (fn, arr ) { return fn(...arr); }
apply 量身定做,传的是数组
1 2 3 function argsAsArray (fn, arr ) { return fn.apply(this , arr); }
call 如果用call就需要使用扩展符打散
1 2 3 function argsAsArray (fn, arr ) { return fn.call(this , ...arr); }
bind 如果bind处理,需要执行
1 2 3 function argsAsArray (fn, arr ) { return fn.bind(this ,...arr)(); }
相关知识点
apply/call/bind (详情见一的第一题)
fn传参问题
题目描述 将函数 fn 的执行上下文改为 obj 对象 输入:
1 function ( ) {return this .greeting + ', ' + this .name + '!!!' ;}, {greeting : 'Hello' , name : 'Rebecca' }
输出:
apply 1 2 3 function speak (fn, obj ) { return fn.apply(obj); }
call 1 2 3 function speak (fn, obj ) { return fn.call(obj); }
bind 1 2 3 function speak (fn, obj ) { return fn.bind(obj)(); }
相关知识点
apply/call/bind 都可以修改执行上下文,如果直接调用fn,this指的是window,如果用 apply/call/bind 可以将this改成对象obj
题目描述 实现函数 functionFunction,调用之后满足如下条件: 1、返回值为一个函数 f 2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ‘, ‘ 3、所有函数的参数数量为 1,且均为 String 类型 输入:
1 functionFunction('Hello' )('world' )
输出:
代码 1 2 3 4 5 6 function functionFunction (str ) { return function (newStr ) { return str + ', ' + newStr; } }
相关知识点
闭包的作用是一个函数可以访问另一个函数作用域的变量。
题目描述 实现函数 makeClosures,调用之后满足如下条件: 1、返回一个函数数组 result,长度与 arr 相同 2、运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同 输入:
1 2 3 [1 , 2 , 3 ], function (x ) { return x * x; };
输出:
使用let+循环 1 2 3 4 5 6 7 8 9 function makeClosures (arr, fn ) { let result = []; for (let i = 0 ; i < arr.length; i++) { result.push(function ( ) { return fn(arr[i]); }); } return result; }
使用map函数 1 2 3 function makeClosures (arr, fn ) { return arr.map(item => fn.bind(this , item)); }
相关知识点
上面的题,如果不用闭包,那么for循环的嘶吼,最后调用函数的时候,i都是arr.length,如果使用闭包,可以是当时循环的i值。
题目描述 已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件: 1、返回一个函数 result,该函数接受一个参数 2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致 输入:
1 2 3 4 var sayIt = function (greeting, name, punctuation ) { return greeting + ', ' + name + (punctuation || '!' ); }; partial(sayIt, 'Hello' , 'Ellie' )('!!!' );
输出:
直接调用 因为没有涉及到this,这里直接用arguments来获取,因为arguments是类数组
1 2 3 4 5 function partial (fn, str1, str2 ) { return function (str3 ) { return fn(str1, str2, str3); } }
改用箭头函数
1 2 3 function partial (fn, str1, str2 ) { return str3 => fn(str1, str2, str3); }
扩展运算符 用扩展运算符拿到参数传入,更加的通用
1 2 3 4 5 function partial (fn, str1, str2 ) { return function (...args ) { return fn(str1, str2, args); } }
call 1 2 3 4 5 function partial (fn, str1, str2 ) { return function (str3 ) { return fn.call(this , str1, str2, str3); } }
apply 1 2 3 4 5 function partial (fn, str1, str2 ) { return function (str3 ) { return fn.apply(this , [str1, str2, str3]); } }
bind 1 2 3 4 5 function partial (fn, str1, str2 ) { return function (str3 ) { return fn.bind(this , str1, str2, str3)(); }; }
或者直接简化
1 2 3 function partial (fn, str1, str2 ) { return fn.bind(this , str1, str2); }
相关知识点
arguments 类数组, 获取长度arguments.length 获取元素用数组下标arguments[0] 获取当前执行的函数 arguments.callee (ES5严格模式下禁用)
题目描述 函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。 输入:
输出:
直接遍历 1 2 3 4 5 6 7 function useArguments ( ) { let count = 0 ; for (let i = 0 ; i < arguments .length; i++) { count += arguments [i]; } return count; }
ES6把arguments转化成数组用数组的方式相加 1 2 3 function useArguments ( ) { return Array .from(arguments ).reduce((prev, item ) => prev + item, 0 ); }
或
1 2 3 function useArguments ( ) { return [...arguments].reduce((pre, item ) => pre + item); }
相关知识点
arguments —— 函数参数的获取和类数组的运算。
题目描述 实现函数 callIt,调用之后满足如下条件 1、返回的结果为调用 fn 之后的结果 2、fn 的调用参数为 callIt 的第一个参数之后的全部参数 输入:无 输出:无
代码 把参数从第一个开始截取,然后调用apply
1 2 3 4 function callIt (fn ) { let newArr = Array .from(arguments ).slice(1 ); return fn.apply(this , newArr); }
相关知识点
题目描述 实现函数 partialUsingArguments,调用之后满足如下条件: 1、返回一个函数 result 2、调用 result 之后,返回的结果与调用函数 fn 的结果一致 3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数 输入: 无 输出:无
用call直接扩展运算符 1 2 3 4 5 6 function partialUsingArguments (fn ) { let args = [].slice.call(arguments , 1 ); return function result (...newArgs ) { return fn.call(this , ...args, ...newArgs); } }
用apply接收数组 1 2 3 4 5 6 function partialUsingArguments (fn ) { let args = [].slice.call(arguments , 1 ); return function result (...newArgs ) { return fn.apply(this , args.concat(newArgs)); } }
bind 1 2 3 4 5 6 function partialUsingArguments (fn ) { let args = [].slice.call(arguments , 1 ); return function result (...newArgs ) { return fn.bind(this , ...args, ...newArgs)(); }; }
相关知识点
arguments/apply/call/bind
题目描述 已知 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 的调用参数 输入:
1 2 3 4 var fn = function (a, b, c ) { return a + b + c }; curryIt(fn)(1 )(2 )(3 );
输出:
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function curryIt (fn ) { const length = fn.length; let args = []; return function curried (arg ) { args.push(arg); if (args.length < length) { return function (arg2 ) { return curried.call(this , arg2); }; } else { return fn.apply(this , args); } } }
相关知识点
js函数式编程 偏函数与柯里化
题目描述 返回参数 a 和 b 的逻辑或运算结果 输入:
输出:
直接或运算符 1 2 3 function or (a, b ) { return a || b; }
利用位运算 位运算中的或运算,返回0或者1,需要转化类型为布尔值
1 2 3 function or (a, b ) { return a | b ? true : false ; }
相关知识点
|| 运算符,a和b都为false,才是false,其中一个有true,就是false | 运算符,是位运算,位置上都是0才返回0,位置上有一个1就返回1,如果返回需要布尔值,需要转化
题目描述 返回参数 a 和 b 的逻辑且运算结果 输入:
输出:
直接且运算符 1 2 3 function and (a, b ) { return a && b; }
利用位运算 位运算的且运算符,返回 0 和 1,需要转化成布尔值
1 2 3 function and (a, b ) { return a & b ? true : false ; }
相关知识点
&& 运算符,a和b都为true,才是true,其中一个有false,就是false & 运算符,是位运算,位置上都是1才返回1,位置上有一个0就返回0,如果返回需要布尔值,需要转化
题目描述 完成函数 createModule,调用之后满足如下要求: 1、返回一个对象 2、对象的 greeting 属性值等于 str1, name 属性值等于 str2 3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ‘, ‘ + name属性值
对象 1 2 3 4 5 6 7 8 9 10 function createModule (str1, str2 ) { let obj = { greeting : str1, name : str2, sayIt :function ( ) { return this .greeting + ', ' + this .name; } } return obj; }
构造函数 1 2 3 4 5 6 7 8 9 10 function createModule (str1, str2 ) { function Obj ( ) { this .greeting = str1; this .name = str2; } Obj.prototype.sayIt = function ( ) { return this .greeting + ', ' + this .name; } return new Obj; }
相关知识点:
题目描述 获取数字 num 二进制形式第 bit 位的值。注意: 1、bit 从 1 开始 2、返回 0 或 1 3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1 输入:
输出:
位运算 1 2 3 4 function valueAtBit (num, bit ) { num >>= bit - 1 ; return num & 1 ; }
或
1 2 3 function valueAtBit (num, bit ) { return (num >> bit - 1 ) % 2 ; }
while循环 1 2 3 4 5 6 7 8 function valueAtBit (num, bit ) { let arr = []; while (num) { arr.push(num % 2 ); num = Math .floor(num / 2 ); } return arr[bit - 1 ]; }
相关知识点
二进制数值运算
取模
位运算符 左移 >> 右移 << 无符号位右移 <<<
题目描述 给定二进制字符串,将其换算成对应的十进制数字 输入:
输出:
parseInt函数 1 2 3 function base10 (str ) { parseInt (str, 2 ); }
每位乘二法 1 2 3 4 5 6 7 8 9 10 11 function base10 (str ) { let res = 0 ; let base = 1 ; for (let i = str.length - 1 ; i >= 0 ; i--) { if (str[i] === "1" ) { res += base; } base *= 2 ; } return res; }
相关知识点
二进制转十进制,从最高位开始乘2,十进制转二进制,除2取余后取逆向
题目描述 将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。 输入:
输出:
使用API转化成二进制然后补空缺 尽量不要前面加字符串,性能消耗大
1 2 3 4 5 6 7 function convertToBinary (num ) { let res = num.toString(2 ); while (res.length < 8 ) { res = '0' + res; } return res; }
转化之后检查位 算法思维,推荐
1 2 3 4 5 6 7 8 9 10 11 12 13 function convertToBinary (num ) { let arr = []; while (num) { arr.push(num % 2 ); num = num >> 1 ; } let str = "" ; let len = arr.length > 8 ? arr.length : 8 ; for (let i = len - 1 ; i >= 0 ; i--) { str = arr[i] ? str + "1" : str + "0" ; } return str; }
相关知识点
题目描述 求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题 输入:
输出:
确定小数的位数然后保证精度是多少位 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function multiply (a, b ) { let arrA = a.toString().split("." ); let arrB = b.toString().split("." ); let count = 0 ; if (arrA[1 ]) { count += arrA.length; a = a * Math .pow(10 , arrA.length); } if (arrB[1 ]) { count += arrB.length; b = b * Math .pow(10 , arrB.length); } return a * b * Math .pow(10 , -count); }
或者直接简写
1 2 3 4 5 6 7 8 function multiply (a, b ) { let strA = a.toString(); let strB = b.toString(); aLen = strA.indexOf("." ) === -1 ? 1 : Math .pow(10 , strA.length - 2 ); bLen = strB.indexOf("." ) === -1 ? 1 : Math .pow(10 , strB.length - 2 ); return (a * aLen) * (b * bLen) / aLen / bLen; }
利用toFixed函数 1 2 3 4 5 6 function multiply (a, b ) { let arrA = a.toString().split("." )[1 ] || "" ; let arrB = b.toString().split("." )[1 ] || "" ; let fix = arrA.length + arrB.length; return (a * b).toFixed(fix); }
相关知识点
javascript小数精度问题
javascript的数值存储是双精度浮点数64位,根据IEEE 754标准,0-51为值,52-62位指数,63位是符号位。 二进制浮点数表示法对0.1这样的有误差。 解决方法就是先升幂再降幂。
题目描述 将函数 fn 的执行上下文改为 obj,返回 fn 执行后的值 输入:
1 2 3 4 5 6 7 8 9 alterContext( function ( ) { return this .greeting + ', ' + this .name + '!' ; }, { name: 'Rebecca' , greeting: 'Yo' } )
输出:
call 1 2 3 function alterContext (fn, obj ) { return fn.call(obj); }
apply 1 2 3 function alterContext (fn, obj ) { return fn.apply(obj); }
bind bind()返回的是一个函数,所以需要立即执行。
1 2 3 function alterContext (fn, obj ) { return fn.bind(obj)(); }
相关知识点
题目描述 给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。 输入:
1 2 3 4 5 6 7 var C = function (name ) { this .name = name; return this ; }; var obj1 = new C('Rebecca' ); alterObjects(C, 'What\'s up' ); obj1.greeting;
输出:
原型对象上添加属性 1 2 3 function alterObjects (constructor, greeting ) { return constructor .prototype .greeting = greeting ; }
相关知识点
题目描述 找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~) 1、返回数组,格式为 key: value 2、结果数组不要求顺序 输入:
1 2 3 4 5 6 var C = function ( ) { this .foo = 'bar' ; this .baz = 'bim' ; }; C.prototype.bop = 'bip' ; iterate(new C());
输出 :
1 ["foo: bar" , "baz: bim" ]
for循环 1 2 3 4 5 6 7 function iterate (obj ) { let res = []; for (let key in obj) { if (obj.hasOwnProperty(key)) res.push(key + ': ' + obj[key]); } return res; }
forEach或 map 1 2 3 4 5 function iterate (obj ) { let res = []; Object .getOwnPropertyNames(obj).forEach(value => res.push(`${value} : ${obj[value]} ` )); return res; }
或者
1 2 3 function iterate (obj ) { return Object .getOwnPropertyNames(obj).map(value => `${value} : ${obj[value]} ` ); }
相关知识点
Object.getOwnPropertyNames(obj), 获取所有的对象自身属性
题目描述 给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false 输入:
输出:
正则表达式 1 2 3 function containsNumber (str ) { return /\d/ .test(str); }
字符串比较ASCII码 1 2 3 4 5 6 7 8 function containsNumber (str ) { for (let i = 0 ; i < str.length; i++) { if (str[i] >= '0' && str[i] <= '9' ) { return true ; } } return false ; }
利用隐式类型转化 1 2 3 4 5 6 7 8 function containsNumber (str ) { for (let i = 0 ; i < str.length; i++) { if (str[i] >= 0 || str[i] <= 9 ) { return true ; } } return false ; }
相关知识点
字符串比较会比较他们的ASCII码值,数字是连续的ASCII码,0123456789分别是48-57,在这个范围内的就可以。
数字字符串和数字比较,会隐式转化成数字,字符串和数字比较,会转化成数字NaN,和数字比较返回false,所以这种方式也可以找到字符串中是否有数字。
题目描述 给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false 输入:
输出:
双指针 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function containsRepeatingLetter (str ) { if (str.length < 2 ) return false ; let left = 0 ; let right = 1 ; while (str[right]) { if (str[left++] === str[right++] && str[left].toLowerCase() >= 'a' && str[left].toLowerCase() <= 'z' && str[right].toLowerCase() >= 'a' && str[right].toLowerCase() <= 'z' ){ return true ; } } return false ; }
正则表达式 小括号表示分组,\1表示引用第一个分组
1 2 3 function containsRepeatingLetter (str ) { return /([a-zA-Z])\1/ .test(str); }
相关知识点
题目描述 给定字符串 str,检查其是否以元音字母结尾 1、元音字母包括 a,e,i,o,u,以及对应的大写 2、包含返回 true,否则返回 false 输入:
输出:
正则表达式 1 2 3 function endsWithVowel (str ) { return /[a,e,i,o,u]$/i .test(str); }
indexOf或includes 1 2 3 function endsWithVowel (str ) { return ['a' ,'e' ,'i' ,'o' ,'u' ].indexOf(str.slice(-1 ).toLowerCase()) === -1 ? false : true ; }
或
1 2 3 function endsWithVowel (str ) { return ['a' ,'e' ,'i' ,'o' ,'u' ].includes(str.slice(-1 ).toLowerCase()); }
相关知识点
字符串方法slice,toLowerCase
数组方法indexOf,includes
正则表达式
题目描述 给定字符串 str,检查其是否包含 连续3个数字 1、如果包含,返回最先出现的 3 个数字的字符串 2、如果不包含,返回 false 输入:
输出:
PS: 这个题我们理解的是三个连续递增的数字,但是题的意思是连续的数字即可。
计数器 1 2 3 4 5 6 7 8 9 10 11 12 13 function captureThreeNumbers (str ) { let start = 0 ; let count = 0 ; for (let i = 0 ; i < str.length; i++) { if (!isNaN (str[i])) { count++; } else { count = 0 ; start = i + 1 ; } } return count >= 3 ? str[start] + str[start + 1 ] + str[start + 2 ] : false ; }
如果是连续递增的数字,要使用双指针这样实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function captureThreeNumbers (str ) { let left = 0 ; let right = 0 ; while (str[right + 1 ] !== undefined ) { if ( Math .abs(str[right + 1 ] - str[right]) === 1 && str[right] >= 0 && str[right] <= 9 ) { right++; } else if (right - left + 1 < 3 ) { left = ++right; } else { return str.substr(left, 3 ); } } return right - left + 1 >= 3 ? str.substr(left, 3 ) : false ; }
正则表达式 1 2 3 4 5 6 7 8 function captureThreeNumbers (str ) { let arr = str.match(/\d{3}/ ); if (arr) { return arr[0 ]; } else { return false ; } }
简写
1 2 3 4 function captureThreeNumbers (str ) { let arr = str.match(/\d{3}/ ); return arr ? arr[0 ] : false ; }
相关知识点
计数器
正则表达式
双指针(算法思维) + 判断连续数字
题目描述 给定字符串 str,检查其是否符合如下格式 1、XXX-XXX-XXXX 2、其中 X 为 Number 类型 输入:
输出:
代码 1 2 3 function matchesPattern (str ) { return /^\d{3}-\d{3}-\d{4}$/ .test(str); }
相关知识点
题目描述 给定字符串 str,检查其是否符合美元书写格式 1、以$ 开始 2、整数部分,从个位起,满 3 个数字用 , 分隔 3、如果为小数,则小数部分长度为 2 4、正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12 或者 $34,344.3 输入:
输出:
代码 正则表达式,从左往右写,依次匹配
1 2 3 function isUSD (str ) { return /^\$[\d]{1,3}(,\d{3})*(\.\d{2})?$/ .test(str); }
相关知识点
题目描述 HTML模块为一个简化版的购物车,tbody为商品列表,tfoot为统计信息,系统会随机在列表中生成一些初始商品信息 1、请完成add函数,在列表后面显示items商品信息。参数items为{name: String, price: Number}组成的数组 2、请完成bind函数,点击每一行的删除按钮(包括通过add增加的行),从列表中删除对应行 3、请注意同步更新统计信息,价格保留小数点后两位 4、列表和统计信息格式请与HTML示例保持一致 5、不要直接手动修改HTML中的代码 6、不要使用第三方库
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <table id ="jsTrolley" > <thead > <tr > <th > 名称</th > <th > 价格</th > <th > 操作</th > </tr > </thead > <tbody > <tr > <td > 产品1</td > <td > 10.00</td > <td > <a href ="javascript:void(0);" > 删除</a > </td > </tr > <tr > <td > 产品2</td > <td > 30.20</td > <td > <a href ="javascript:void(0);" > 删除</a > </td > </tr > <tr > <td > 产品3</td > <td > 20.50</td > <td > <a href ="javascript:void(0);" > 删除</a > </td > </tr > </tbody > <tfoot > <tr > <th > 总计</th > <td colspan ="2" > 60.70(3件商品)</td > </tr > </tfoot > </table >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 body ,html { padding : 0 ; margin : 0 ; font-size : 14px ; color : #000000 ; } table { border-collapse : collapse; width : 100% ; table-layout : fixed; } thead { background : #3d444c ; color : #ffffff ; } td ,th { border : 1px solid #e1e1e1 ; padding : 0 ; height : 30px ; line-height : 30px ; text-align : center; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 function add (items ) { var tbody = getTbody(); var tfoot = getTfoot(); var num = tbody.children.length; var total = tfoot.innerText.match(/^.*\t(\d*\.?\d*)\(.*\)$/ )[1 ]; var price = parseFloat (total); var tr = "" ; for (let i in items) { price = parseFloat ((price + items[i].price).toFixed(2 )); tr += `<tr> <td>${items[i].name} </td> <td>${items[i].price.toFixed(2 )} </td> <td><a href="javascript:void(0);">删除</a></td> </tr>` ; num++; } var tf = `<tr><th>总计</th><td colspan="2">${price.toFixed( 2 )} (${num} 件商品)</td></tr>` ; tfoot.innerHTML = tf; tbody.innerHTML = tbody.innerHTML + tr; } function bind ( ) { var tbody = getTbody(); var tfoot = getTfoot(); tbody.addEventListener("click" , (event ) => { var num = tbody.children.length; if (event.target.tagName == "A" ) { var price = event.target.parentElement.parentElement.innerText.match( /^.*\t(\d*\.?\d*)\t.*$/ )[1 ]; var total = tfoot.innerText.match(/^.*\t(\d*\.?\d*)\(.*\)$/ )[1 ]; price = parseFloat ((parseFloat (total) - price).toFixed(2 )); var tf = ` <tr><th>总计</th><td colspan="2">${price.toFixed(2 )} (${ num - 1 } 件商品)</td></tr> ` ; tfoot.innerHTML = tf; event.target.parentElement.parentElement.remove(); } }); } function getTbody ( ) { return document .getElementById("jsTrolley" ).getElementsByTagName("tbody" )[0 ]; } function getTfoot ( ) { return document .getElementsByTagName("tfoot" )[0 ]; }
相关知识点
题目描述 系统会在tbody中随机生成一份产品信息表单,如html所示。 请完成 sort 函数,根据参数的要求对表单所有行进行重新排序。 1、type为id、price或者sales,分别对应第1 ~ 3列 2、order为asc或者desc,asc表示升序,desc为降序 3、例如 sort(‘price’, ‘asc’) 表示按照price列从低到高排序 4、所有表格内容均为数字,每一列数字均不会重复 5、不要使用第三方插件
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <table > <thead > <tr > <th > id</th > <th > price</th > <th > sales</th > </tr > </thead > <tbody id ="jsList" > <tr > <td > 1</td > <td > 10.0</td > <td > 800</td > </tr > <tr > <td > 2</td > <td > 30.0</td > <td > 600</td > </tr > <tr > <td > 3</td > <td > 20.5</td > <td > 700</td > </tr > <tr > <td > 4</td > <td > 40.5</td > <td > 500</td > </tr > <tr > <td > 5</td > <td > 60.5</td > <td > 300</td > </tr > <tr > <td > 6</td > <td > 50.0</td > <td > 400</td > </tr > <tr > <td > 7</td > <td > 70.0</td > <td > 200</td > </tr > <tr > <td > 8</td > <td > 80.5</td > <td > 100</td > </tr > </tbody > </table >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 body , html { padding : 0 ; margin : 0 ; font-size : 14px ; color : #000000 ; } table { border-collapse : collapse; width : 100% ; table-layout : fixed; } thead { background : #3d444c ; color : #ffffff ; } td , th { border : 1px solid #e1e1e1 ; padding : 0 ; height : 30px ; line-height : 30px ; text-align : center; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function sort (type, order ) { var jsList = document .getElementById("jsList" ); var trs = jsList.getElementsByTagName("tr" ); var arrTrs = Array .prototype.slice.call(trs); var index = 0 ; if (type == "id" ) { index = 0 ; } else if (type == "price" ) { index = 1 ; } else if (type == "sales" ) { index = 2 ; } arrTrs.sort(function (value1, value2 ) { var td1 = value1.getElementsByTagName("td" )[index].innerHTML; var td2 = value2.getElementsByTagName("td" )[index].innerHTML; if (order == "asc" ) { return td1 - td2; } if (order == "desc" ) { return td2 - td1; } }); arrTrs.forEach((tr ) => { jsList.appendChild(tr); }); }
相关知识点
题目描述 页面中存在id=jsContainer的DOM元素。 该DOM元素内会给出一段随机文本,可能包含一些链接,比如https://www.baidu.com,或者 www.baidu.com?from=onlineExam,如果出现链接文本,请给该链接文本加上链接标签,用户点击后能直接在新窗口中打开该链接。 请完成 link 函数,完成该功能 1、container只有纯文本内容,不包含其他dom元素 2、识别所有以http://、https://或者www.开始的链接 3、所有www.开头的链接,默认使用 http 协议 4、所有链接在新窗口打开
代码 .html:
1 2 3 <div id ="jsContainer" > 这里会给出一段随机文本,可能包含一些链接,比如https://www.baidu.com,或者 www.baidu.com?from=onlineExam,如果出现链接文本,请给该链接文本加上链接标签,用户点击后能直接在新窗口中打开该链接。 </div >
.css:
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function link ( ) { const jsContainer = document .querySelector("#jsContainer" ); let reg = /(https?:\/\/)?(www\.\w+(\.(com|cn))*([?]\w+=\w*(&\w+=\w*)*)?(#\w+)?)/g; jsContainer.innerHTML = jsContainer.innerHTML.replace( reg, function (...args ) { if (args[1 ]) { return `<a target="_blank" href="${args[1 ]} ${args[2 ]} ">${args[0 ]} </a>` ; } else { return `<a target="_blank" href="http://${args[2 ]} ">${args[0 ]} </a>` ; } } ); }
相关知识点
题目描述 倒计时是web开发中常见的组件,请完成second和render两个函数,完成倒计时的显示部分 1、second函数的输入为整数,返回{day: Int, hour: Int, min: Int, second: Int} 2、render函数的输入为second函数的输出,将数据在页面对应的DOM元素上显示出来,格式如html所示 3、如果day为0,隐藏对应的DOM元素,否则显示(请直接使用已经实现的css代码) 4、数值不足两位,前面补充0
代码 .html:
1 2 3 4 5 6 <div id ="jsCountdown" > <span > 01天</span > <span > 02:</span > <span > 03:</span > <span > 04</span > </div >
.css:
1 2 3 .hide { display : none; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 function second (second ) { var day = Math .floor(second / (60 * 60 * 24 )); second -= day * (60 * 60 * 24 ); var hour = Math .floor(second / (60 * 60 )); second -= hour * (60 * 60 ); var min = Math .floor(second / 60 ); second -= min * 60 ; return { day, hour, min, second, }; } function render (data ) { var jsCountdown = document .getElementById("jsCountdown" ); var times = jsCountdown.children; if (data.day == 0 ) { times[0 ].className = "hide" ; } else { times[0 ].innerHTML = format(data.day) + "天" ; } times[1 ].innerHTML = format(data.hour) + ":" ; times[2 ].innerHTML = format(data.min) + ":" ; times[3 ].innerHTML = format(data.second); function format (num ) { var result = num.toString(); if (num < 10 && num >= 0 ) { result = "0" + result; } return result; } }
相关知识点
题目描述 页面左边为可以使用的拼图,右边为拼图的位置,两者通过序列号对应,页面元素均已经标记id。 请完成drag函数,当执行drag后,可以实现如下需求 1.用户可以把左边的拼图块全部移到右边对应位置,全部移动完成要求弹出提示框显示拼图成功(提示框为id标记为success的div标签) 2.如果在移动途中松开鼠标,则 2.1 左侧拼图模块如果没有和目标位置发生重合,拼图模块需要回到原来的位置 2.2 如果拼图模块和目标位置有2/3以上重合则认为拼图成功,此时拼图模块移动到目标位置,并且无法再次拖动 3.在移动时鼠标需要一直在拼图模块上,否则拼图模块停止移动 4.当前页面默认已经调用drag函数,请不要删除该调用语句 5.请不要手动修改html和css 6.不要使用第三方插件 7.请使用ES5语法
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 <div class ='title' > 将左侧模块移动到右侧对应位置完成拼图</div > <div class ='pos src' id ='src-1' > 1</div > <div class ='pos src' id ='src-2' > 2</div > <div class ='pos src' id ='src-3' > 3</div > <div class ='pos dest' id ='dest-1' > 1</div > <div class ='pos dest' id ='dest-2' > 2</div > <div class ='pos dest' id ='dest-3' > 3</div > <div class ='success' id ='success' > 拼图完成</div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 * { margin : 0px ; padding : 0px ; } html { height : 100% ; } body { height : 100% ; min-width : 300px ; display : flex; justify-content : center; align-items : center; } .pos { width : 50px ; height : 50px ; position : absolute; color : black; line-height : 50px ; text-align : center; font-size : 25px ; cursor : pointer; user-select: none; } .dest { border-color : black; border-width : 1px ; border-style : solid; } #src-1 { top : 50px ; left : 10px ; background-color : red; z-index : 100 ; } #src-2 { top : 150px ; left : 10px ; background-color : yellow; z-index : 100 ; } #src-3 { top : 250px ; left : 10px ; background-color : green; z-index : 100 ; } #dest-1 { top : 250px ; right : 10px ; } #dest-2 { top : 150px ; right : 10px ; } #dest-3 { top : 50px ; right : 10px ; } .success { line-height : 50px ; height : 50px ; font-size : 30px ; text-align : center; color : red; background-color : black; padding : 25px ; display : none; } .title { text-align : center; font-size : 20px ; position : absolute; top : 10px ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 drag(); function drag ( ) { var src1 = document .getElementById("src-1" ); var src2 = document .getElementById("src-2" ); var src3 = document .getElementById("src-3" ); var dest1 = document .getElementById("dest-1" ); var dest2 = document .getElementById("dest-2" ); var dest3 = document .getElementById("dest-3" ); var success = document .getElementById("success" ); var successNum = 0 ; function MoveEle (ele ) { this .ele = ele; this .mouse = { mouseEleClient: { t: 0 , l: 0 , }, mouseSuo: false , }; this .isTarget = true ; this .offsetLeft = ele.offsetLeft; this .offsetTop = ele.offsetTop; } MoveEle.prototype.init = function (fn ) { var ele = this .ele; var mouse = this .mouse; var _this = this ; ele.onmousedown = function (e ) { if (_this.isTarget) { e = e || window .event; var l = e.clientX; var t = e.clientY; mouse.mouseEleClient.t = t - this .offsetTop; mouse.mouseEleClient.l = l - this .offsetLeft; mouse.mouseSuo = true ; } }; ele.onmouseup = function (e ) { mouse.mouseSuo = false ; fn(this .offsetTop, this .offsetLeft); }; window .addEventListener("mousemove" , function (e ) { if (mouse.mouseSuo) { e = e || window .event; var l = e.clientX; var t = e.clientY; ele.style.top = t - mouse.mouseEleClient.t + "px" ; ele.style.left = l - mouse.mouseEleClient.l + "px" ; } }); }; MoveEle.prototype.toTarget = function (left, top ) { this .ele.style.top = ++top + "px" ; this .ele.style.left = ++left + "px" ; this .isTarget = false ; }; MoveEle.prototype.toOrigin = function ( ) { this .ele.style.top = this .offsetTop + "px" ; this .ele.style.left = this .offsetLeft + "px" ; }; function TargetEle (ele ) { this .ele = ele; this .target = { coincidence: 2 / 3 , isTarget: false , }; this .offsetTop = ele.offsetTop; this .offsetLeft = ele.offsetLeft; } TargetEle.prototype.isTarget = function (t, l, w, h ) { this .ele.offsetWidth; var xdt = Math .abs(t - this .offsetTop); var xdl = Math .abs(l - this .offsetLeft); h = h || this .ele.offsetHeight; w = w || this .ele.offsetWidth; var tarh = this .ele.offsetHeight - xdt; var tarw = this .ele.offsetWidth - xdl; if ( (tarh * tarw) / (h * w) > this .target.coincidence && tarh > 0 && tarw > 0 ) { this .target.isTarget = true ; return true ; } return false ; }; var srcME_1 = new MoveEle(src1); var desTE_1 = new TargetEle(dest1); srcME_1.init(function (t, l ) { if (desTE_1.isTarget(t, l)) { srcME_1.toTarget(desTE_1.offsetLeft, desTE_1.offsetTop); successNum++; if (successNum == 3 ) successFn(); } else { srcME_1.toOrigin(); } }); var srcME_2 = new MoveEle(src2); var desTE_2 = new TargetEle(dest2); srcME_2.init(function (t, l ) { if (desTE_2.isTarget(t, l)) { srcME_2.toTarget(desTE_2.offsetLeft, desTE_2.offsetTop); successNum++; if (successNum == 3 ) successFn(); } else { srcME_2.toOrigin(); } }); var srcME_3 = new MoveEle(src3); var desTE_3 = new TargetEle(dest3); srcME_3.init(function (t, l ) { if (desTE_3.isTarget(t, l)) { srcME_3.toTarget(desTE_3.offsetLeft, desTE_3.offsetTop); successNum++; if (successNum == 3 ) successFn(); } else { srcME_3.toOrigin(); } }); function successFn ( ) { success.style.display = "block" ; } }
提交未通过,不过可以正常运行
相关知识点
题目描述 双色球由33个红球和16个蓝球组成,1注双色球包括6个不重复的红球和1个蓝球。 请阅读给出的页面和代码,完成 randomFn 函数,实现“随机一注”功能,要求如下:
函数返回:
1.以字符串形式输出“随机一注”结果,选中的红蓝球用”|”隔开,红球在前,号码间用半角逗号隔开,如”06,10,13,18,23,27|05”
2.红球和蓝球号码排列顺序 需与页面展示的顺序对应
页面交互:
1.将选中的红球和蓝球(页面中对应DOM元素)用class=”active”高亮
2.将选中的球按号码从小到大排列,移至所属组的前方,结果如示意图所示
3.每次执行 randomFn 函数,输出符合要求且不完全重复
注意:
1、请使用原生JavaScript操作DOM元素,不要增加、删除DOM元素或修改css
2、请使用ES5语法
3、答题时不要使用第三方插件
4、运行浏览器为chrome浏览器
5、可能涉及的点
// element.className // element.classList // element.classList.add // element.classList.remove // element.getAttribute // element.setAttribute // element.innerHTML // element.insertBefore // element.parentNode
// document.querySelector // document.querySelectorAll // document.getElementsByTagName // document.getElementsByClassName
// Array.sort // Array.push // Array.join // Array.indexOf // Array.forEach // Array.map
// Math.random // Math.floor
// Number.toString()
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <div class ="main" > <div class ="balls red" > <span > 红球</span > <div class ="balls-wp" > <b > 01</b > <b > 02</b > <b > 03</b > <b > 04</b > <b > 05</b > <b > 06</b > <b > 07</b > <b > 08</b > <b > 09</b > <b > 10</b > <b > 11</b > <b > 12</b > <b > 13</b > <b > 14</b > <b > 15</b > <b > 16</b > <b > 17</b > <b > 18</b > <b > 19</b > <b > 20</b > <b > 21</b > <b > 22</b > <b > 23</b > <b > 24</b > <b > 25</b > <b > 26</b > <b > 27</b > <b > 28</b > <b > 29</b > <b > 30</b > <b > 31</b > <b > 32</b > <b > 33</b > </div > </div > <div class ="balls blue" > <span > 蓝球</span > <div class ="balls-wp" > <b > 01</b > <b > 02</b > <b > 03</b > <b > 04</b > <b > 05</b > <b > 06</b > <b > 07</b > <b > 08</b > <b > 09</b > <b > 10</b > <b > 11</b > <b > 12</b > <b > 13</b > <b > 14</b > <b > 15</b > <b > 16</b > </div > </div > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 .main .balls { width : 450px ; padding : 30px 10px 10px ; margin-bottom : 20px ; position : relative; border-radius : 4px ; } .main .balls :after { content: "\20" ; clear : both; display : block; height : 0 ; overflow : hidden; } .main .balls span { position : absolute; left : 12px ; top : 5px ; font-size : 13px ; } .main b { float : left; width : 30px ; height : 30px ; font-size : 15px ; background : #fff ; border : 1px solid; border-radius : 50% ; line-height : 30px ; text-align : center; margin-right : 8px ; margin-bottom : 8px ; cursor : pointer; } .main .red .active { background : #f56c6c ; color : #fff ; } .main .blue .active { background : #3a8ee6 ; color : #fff ; } .main .red { background : #feeff0 ; } .main .red b { border-color : #f56c6c ; } .main .blue { background : #ecf8ff ; } .main .blue b { border-color : #3a8ee6 ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 randomFn(); function randomFn ( ) { var res = "" ; function randomArr (min, max, len ) { var numArr = []; while (numArr.length < len) { var colorNum = randomHelper(min, max); if (numArr.indexOf(colorNum) === -1 ) { numArr.push(colorNum); } } function randomHelper (min, max ) { var num = Math .floor(Math .random() * (max - min + 1 ) + min); if (num <= 9 ) { return "0" + num; } else { return num + "" ; } } numArr.sort((a, b ) => Number (a) - Number (b)); return numArr; } var redArr = randomArr(1 , 33 , 6 ); res += redArr.join("," ); var blueArr = randomArr(1 , 16 , 1 ); res += "|" + blueArr[0 ]; var red = document .querySelectorAll(".red b" ); var blue = document .querySelectorAll(".blue b" ); mutual(red, redArr, "red" ); mutual(blue, blueArr, "blue" ); function mutual (colorB, arr, color ) { for (let i = 0 ; i < colorB.length; i++) { if (arr.indexOf(colorB[i].innerHTML) !== -1 ) { colorB[i].remove(); } } var colorTemp = document .querySelector("." + color + " .balls-wp" ); for (var i = arr.length - 1 ; i >= 0 ; i--) { var addColor = document .createElement("b" ); addColor.classList.add("active" ); addColor.innerHTML = arr[i]; colorTemp.insertBefore(addColor, colorTemp.childNodes[0 ]); } } return res; }
相关知识点
题目描述 本题展示了一个简化版的搜索框智能提示功能,请按照如下要求完成suggest函数。 1、当输入框的值发生变化时,系统会调用suggest函数,用于显示/隐藏智能提示数据,参数items为一个字符串数组。 2、当items中的字符串和输入框的值匹配时,将匹配的数据依次渲染在ul下的li节点中,并显示.js-suggest节点,否则移除ul下的所有li节点,并隐藏.js-suggest节点 3、输入框的值需要移除两侧空白再进行匹配 4、输入框的值为空时,按照全部不匹配处理 5、字符串使用模糊匹配,比如”北大”能匹配”北大”和”北京大学”,但不能匹配”大北京”,即按照 /北.?大. ?/ 这个正则进行匹配 6、通过在.js-suggest节点上添加/移除 hide 这个class来控制该节点的隐藏/显示 7、当前界面是执行 suggest([‘不匹配数据’, ‘根据输入框的值’, ‘从给定字符串数组中筛选出匹配的数据,依次显示在li节点中’, ‘如果没有匹配的数据,请移除所有li节点,并隐藏.js-suggest节点’]) 后的结果 8、请不要手动修改html和css 9、不要使用第三方插件 10、请使用ES5语法
代码 .html:
1 2 3 4 5 6 7 8 9 10 <div class ="search" > <div > <input type ="text" class ="js-input" value ="的" > </div > <div class ="js-suggest" > <ul > <li > 根据输入框的值</li > <li > 从给定字符串数组中筛选出匹配的数据,依次显示在li节点中</li > <li > 如果没有匹配的数据,请移除所有li节点,并隐藏.js-suggest节点</li > </ul > </div > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 .search { position : relative; } .js-input { width : 450px ; height : 22px ; line-height : 22px ; font-size : 16px ; padding : 8px ; border : 1px solid #cccccc ; outline : none; } .js-suggest { width : 466px ; font-size : 14px ; border : 1px solid #cccccc ; background : #ffffff ; position : absolute; left : 0 ; top : 39px ; } .js-suggest .hide { display : none; } .js-suggest ul { display : block; list-style : none; padding : 0 ; margin : 0 ; } .js-suggest ul li { color : #000 ; font : 14px arial; line-height : 25px ; padding : 0 8px ; position : relative; cursor : default; } .js-suggest ul li :hover { background : #f0f0f0 ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 function suggest (items ) { var divStr = document .querySelector('div input' ).value; divStr = divStr.trim(); var jsS = document .querySelector('.js-suggest' ) var oldli = document .querySelectorAll('.js-suggest ul li' ); for (var i = 0 ; i < oldli.length; i++) { oldli[i].remove(); } var reg = new RegExp (divStr.replace(/([\\\/\(\)\+\*\?\:\\[\]\^\$])/g , "\\$1" ).replace(/(\\.)/g , "$1.*?" )); if (!divStr) { jsS.classList.add('hide' ); return ; } var ifHide = true ; for (var i = 0 ; i < items.length; i++) { if (reg.test(items[i])) { ifHide = false ; var newLi = document .createElement('li' ); newLi.innerHTML = items[i] document .querySelector('ul' ).appendChild(newLi); jsS.classList.remove('hide' ); } } if (ifHide) { jsS.classList.add('hide' ); } }
相关知识点
题目描述 页面上存在id为jsBlink的下划线闪动节点,请按照如下需求实现 output 函数 1、函数 output 接收一个字符串参数,每隔200毫秒在闪动节点之前逐个显示字符 2、请新建span节点放置每个字符,其中span必须存在class “word”,并随机加上 color0 ~ color23 中的任一个class(请使用系统随机函数) 3、每次输出指定字符串前,请将闪动节点之前的所有其他节点移除 4、不要销毁或者重新创建闪动节点 5、如果输出字符为空格、<、>,请分别对其进行HTML转义,如果是\n请直接输出<br />,其他字符不需要做处理 6、请不要手动调用output函数 7、当前界面为系统执行 output(‘hello world\n你好世界’) 之后,最终的界面,过程请参考以下图片
8、请不要手动修改html和css 9、不要使用第三方插件 10、请使用ES5语法
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <div class ="content" > <span class ="word color23" > h</span > <span class ="word color22" > e</span > <span class ="word color4" > l</span > <span class ="word color24" > l</span > <span class ="word color17" > o</span > <span class ="word color2" > </span > <span class ="word color9" > w</span > <span class ="word color3" > o</span > <span class ="word color1" > r</span > <span class ="word color23" > l</span > <span class ="word color15" > d</span > <br > <span class ="word color15" > 你</span > <span class ="word color13" > 好</span > <span class ="word color16" > 世</span > <span class ="word color19" > 界</span > <span class ="blink" id ="jsBlink" > |</span > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 html ,body { margin : 0 ; } .color1 { color : #e60012 ; } .color2 { color : #eb6100 ; } .color3 { color : #f39800 ; } .color4 { color : #fcc800 ; } .color5 { color : #fff100 ; } .color6 { color : #cfdb00 ; } .color7 { color : #8fc31f ; } .color8 { color : #22ac38 ; } .color9 { color : #009944 ; } .color10 { color : #009b6b ; } .color11 { color : #009e96 ; } .color12 { color : #00a0c1 ; } .color13 { color : #00a0e9 ; } .color14 { color : #0086d1 ; } .color15 { color : #0068b7 ; } .color16 { color : #00479d ; } .color17 { color : #1d2088 ; } .color18 { color : #601986 ; } .color19 { color : #920783 ; } .color20 { color : #be0081 ; } .color21 { color : #e4007f ; } .color22 { color : #e5006a ; } .color23 { color : #e5004f ; } .color24 { color : #e60033 ; } .word { font-size : 20px ; } .content { text-align : center; font-size : 0 ; } .blink { font-size : 20px ; animation : fade 500ms infinite; -webkit-animation : fade 500ms infinite; } @keyframes fade { from { opacity : 1 ; } 50% { opacity : 0 ; } to { opacity : 1 ; } }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 function output (str ) { var contents = document .getElementsByClassName("content" ); var jsBlink = document .getElementById("jsBlink" ); var childs = contents[0 ].childNodes; while (childs.length > 0 ) { if (childs[0 ] == jsBlink) { break ; } contents[0 ].removeChild(childs[0 ]); } var i = 0 ; var fun = setInterval (function ( ) { if (i == str.length) clearInterval (fun); else { var c = str[i]; if (c == "\n" ) { var br = document .createElement("br" ); contents[0 ].insertBefore(br, jsBlink); } else { var newSpan = document .createElement("span" ); newSpan.className = "word color" + (Math .floor(Math .random() * 24 ) + 1 ); if (c == "<" ) { c = "<" ; } else if (c == ">" ) { c = ">" ; } else if (c == " " ) { c = " " ; } newSpan.innerHTML = c; contents[0 ].insertBefore(newSpan, jsBlink); } i++; } }, 200 ); }
相关知识点
题目描述 系统会随机生成id为jsLayout的 m x n 表格(m >= 3, n >= 3),请按照如下需求实现bind函数
1、bind 函数为每个td节点绑定click事件,当某个td节点被点击时class变为current,同时以该td为中心的九宫格td节点class变为wrap,具体效果参考以下图片 2、每次click后,请清空所有不需要变动的td节点的class 3、请不要手动调用bind函数 4、当前界面为系统生成 10 * 10 表格,执行 bind 函数,并点击第一个td后的效果 5、请不要手动修改html和css 6、不要使用第三方插件 7、请使用ES5语法
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <table id ="jsLayout" > <tbody > <tr > <td class ="current" > </td > <td class ="wrap" > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td class ="wrap" > </td > <td class ="wrap" > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > </tbody > </table >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 body , html { margin : 0 ; } table { border-collapse : collapse; table-layout : fixed; margin : 10px auto; } td { border : 1px solid #E1E1E1 ; padding : 0 ; width : 30px ; height : 30px ; cursor : pointer; } .current { background : #1D2088 ; } .wrap { background : #00A0E9 ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 window .onload = function ( ) { bind(); }; function bind ( ) { const n = 10 ; var tdArr = document .getElementById("jsLayout" ).getElementsByTagName("td" ); for (var i = 0 ; i < tdArr.length; i++) { (function (index ) { tdArr[index].onclick = function ( ) { var row = parseInt (index / n); var col = index % n; for (var j = 0 ; j < tdArr.length; j++) { tdArr[j].className = "" ; } var prevRow = row - 1 >= 0 ? row - 1 : row; var nextRow = row + 1 <= n - 1 ? row + 1 : row; var prevCol = col - 1 >= 0 ? col - 1 : col; var nextCol = col + 1 <= n - 1 ? col + 1 : col; tdArr[prevRow * n + prevCol].className = "wrap" ; tdArr[prevRow * n + col].className = "wrap" ; tdArr[prevRow * n + nextCol].className = "wrap" ; tdArr[row * n + prevCol].className = "wrap" ; tdArr[row * n + nextCol].className = "wrap" ; tdArr[nextRow * n + prevCol].className = "wrap" ; tdArr[nextRow * n + col].className = "wrap" ; tdArr[nextRow * n + nextCol].className = "wrap" ; tdArr[row * n + col].className = "current" ; }; })(i); } }
提交未通过,不过可以正常运行
相关知识点
一维数组二维数组转换
边界值处理
原生js函数DOM操作
题目描述 本题展示了一个分页组件,界面中存在id=jsContainer的节点A,系统会随机实例化各种Pagination实例,请按照如下要求补充完成Pagination函数。 1、最多连续显示5页,居中高亮显示current页(如demo1所示) 2、total <= 1 时,隐藏该组件(如demo2所示) 3、如果total<=5,则显示全部页数,隐藏“首页”和“末页”元素(如demo3所示) 4、当current居中不足5页,向后(前)补足5页,隐藏“首页”(“末页”)元素(如demo4和demo5所示) 5、total、current均为正整数,1 <= current <= total 6、当前界面中,节点A为系统执行 new Pagination(节点A,20, 10) 后的展示效果 7、请不要手动修改html和css 8、不要使用第三方插件
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 <div > <div id ="jsContainer" > <ul class ="pagination" > <li > 首页</li > <li > 8</li > <li > 9</li > <li class ="current" > 10</li > <li > 11</li > <li > 12</li > <li > 末页</li > </ul > </div > <div class ="demo" > <div > (Demo1) total: 10,current: 4</div > <ul class ="pagination" > <li > 首页</li > <li > 2</li > <li > 3</li > <li class ="current" > 4</li > <li > 5</li > <li > 6</li > <li > 末页</li > </ul > </div > <div class ="demo" > <div > (Demo2) total: 0,current: 0</div > <ul class ="pagination hide" > </ul > </div > <div class ="demo" > <div > (Demo3) total: 3,current: 2</div > <ul class ="pagination" > <li > 1</li > <li class ="current" > 2</li > <li > 3</li > </ul > </div > <div class ="demo" > <div > (Demo4) total: 10,current: 2</div > <ul class ="pagination" > <li > 1</li > <li class ="current" > 2</li > <li > 3</li > <li > 4</li > <li > 5</li > <li > 末页</li > </ul > </div > <div class ="demo" > <div > (Demo5) total: 10,current: 9</div > <ul class ="pagination" > <li > 首页</li > <li > 6</li > <li > 7</li > <li > 8</li > <li class ="current" > 9</li > <li > 10</li > </ul > </div > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 .demo { margin-bottom : 20px ; border : 1px solid #ebedf0 ; border-radius : 2px ; padding : 10px ; } .demo div { margin-bottom : 10px ; font-size : 14px ; } .pagination { box-sizing : border-box; margin : 0 ; padding : 0 ; font-size : 14px ; line-height : 1.5 ; list-style : none; display : inline-block; } .pagination .hide { display : none; } .pagination li { position : relative; display : inline-block; float : left; height : 32px ; margin : 0 ; padding : 0 15px ; line-height : 30px ; background : #fff ; border : 1px solid #d9d9d9 ; border-top-width : 1.02px ; border-left : 0 ; cursor : pointer; transition : color 0.3s , border-color 0.3s ; } .pagination li :first -child { border-left : 1px solid #d9d9d9 ; border-radius : 4px 0 0 4px ; } .pagination li :last-child { border-radius : 0 4px 4px 0 ; } .pagination li :first -child { box-shadow : none !important ; } .pagination li .current { border-color : #1890ff ; color : #1890ff ; border-left : 1px solid #1890ff ; } .pagination li .current :not (:first -child) { margin-left : -1px ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 function Pagination (container, total, current ) { this .total = total; this .current = current; this .html = html; this .val = val; this .el = document .createElement("ul" ); if (!this .el) return ; this .el.innerHTML = this .html(); container.appendChild(this .el); this .el.className = total > 1 ? "pagination" : "pagination hide" ; function html ( ) { if (this .total <= 1 ) return "" ; if (this .current > this .total) return "" ; if (this .total <= 5 ) return getPaginationHTML(1 , this .total, this .current, this .total); if (this .current < 3 ) return getPaginationHTML(1 , 5 , this .current, this .total); if (this .current + 2 > this .total) return getPaginationHTML( this .total - 4 , this .total, this .current, this .total ); return getPaginationHTML( this .current - 2 , this .current + 2 , this .current, this .total ); } function getPaginationHTML (start, end, current, total ) { var str = "" ; if (start > 1 ) { str += "<li>首页</li>" ; } for (var i = start; i <= end; i++) { if (i === current) { str += '<li class="current">' + i + "</li>" ; } else { str += "<li>" + i + "</li>" ; } } if (total > 5 && current + 2 <= total) { str += "<li>末页</li>" ; } return str; } function val (current ) { if (arguments .length === 0 ) return this .current; if (current < 1 || current > this .total || current === this .current) return ; this .current = current; this .el.innerHTML = this .html(); } }
相关知识点
题目描述 界面中存在id=jsContainer的节点A,系统会随机生成id为jsLayout的 m行 x n列 表格(m >= 1, n >= 1),并随机选中一个td节点,请按照如下需求实现bind函数 1、bind 函数为document绑定keydown事件,当系统触发上(键值38)下(键值40)左(键值37)右(键值39)按键时,请找到当前选中的td节点,并根据当前指令切换高亮节点,具体效果参考以下图片 2、在第一列往左移动则到达最后一列;在最后一列往右移动则到达第一列;在第一行往上移动则到达最后一行;在最后一行往下移动则到达第一行; 3、请不要手动调用bind函数 4、当前界面为系统在节点A中生成 9 * 9 表格并随机选中一个td节点后的效果 5、请不要手动修改html和css,请不要修改js中的事件绑定方式 6、不要使用第三方插件
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <div id ="jsContainer" > <table class ="game" > <tbody > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td class ="current" > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > <tr > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > <td > </td > </tr > </tbody > </table > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 table .game { font-size : 14px ; border-collapse : collapse; width : 100% ; table-layout : fixed; } table .game td { border : 1px solid #e1e1e1 ; padding : 0 ; height : 30px ; text-align : center; } table .game td .current { background : #1890ff ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 function bind ( ) { const game = document .getElementsByTagName("tbody" )[0 ]; let rowIdx = null , colIdx = null ; const m = game.children.length, n = game.children[0 ].children.length; document .onkeydown = (event ) => { if (!event) return ; var code = event.keyCode || "" ; if (!{ 37 : 1 , 38 : 1 , 39 : 1 , 40 : 1 }[code]) return ; event.preventDefault && event.preventDefault(); const current = game.getElementsByClassName("current" )[0 ]; for (let i = 0 ; i < m; i++) { for (let j = 0 ; j < n; j++) { let item = game.children[i].children[j]; if (item.className === "current" ) { rowIdx = i; colIdx = j; break ; } } if (rowIdx || rowIdx === 0 ) break ; } current.className = "" ; if (code === 38 ) { colIdx === 0 ? (colIdx = m - 1 ) : colIdx--; } else if (code === 40 ) { colIdx === m - 1 ? (colIdx = 0 ) : colIdx++; } else if (code === 37 ) { rowIdx === 0 ? (rowIdx = n - 1 ) : rowIdx--; } else if (code === 39 ) { rowIdx === n - 1 ? (rowIdx = 0 ) : rowIdx++; } game.children[colIdx].children[rowIdx].className = "current" ; }; }
相关知识点
题目描述 页面上存在id=jsContainer的节点A,系统会随机在节点A中生成文档片段,请按照如下需求实现 dom2json 函数 1、dom2json需要分析整个节点A的dom结构,并将其结构转换为对应的json对象 2、需要获取dom结构的标签名称(tag),所有属性(attributes),子节点(children) 3、文档片段中的属性形式均为 name=”value”,解析之后的格式为{name: value}, 属性值为String类型,不需要做解析 4、随机生成的文档片段中,只包含 nodeType 为1(element)和3(text)的节点,不需要考虑其他节点类型 5、纯文本也视为一个节点, json格式为 {tag: ‘text’, content: ‘文本内容’},content为文本内容执行trim后的结果,如果该结果为空,则忽略当前节点 6、返回结果中的标签名称不区分大小写 7、如果节点不包含属性值或者子节点,其对应的结果中需要保留attributes以及children字段,例如 {tag: ‘div’, attributes: {}, children: []} 8、当前界面执行dom2json之后的结果为如下图所示 9、请不要手动修改html和css 10、不要使用第三方插件
代码 .html:
1 2 3 4 5 6 7 8 <div id ="jsContainer" > <ul class ="js-test" id ="jsParent" > <li data-index ="0" > 1</li > <li data-index ="1" > 2</li > </ul > <span style ="font-weight: bold;" > 3</span > 4 </div >
.css:
1 2 3 4 body { margin : 0 ; font-size : 14px ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 function dom2json ( ) { const jsContainer = document .getElementById("jsContainer" ); function handleDom (node ) { let vnode = { tag: node.tagName.toLowerCase(), attributes: {}, children: [], }; let attributes = node.attributes, childNodes = node.childNodes; if (attributes.length > 0 ) { for (let i = 0 ; i < attributes.length; i++) { let item = attributes[i]; vnode.attributes[item.nodeName] = item.nodeValue; } } if (childNodes.length > 0 ) { for (let i = 0 ; i < childNodes.length; i++) { let item = childNodes[i]; if (item.nodeType === Node.TEXT_NODE) { if (item.textContent.trim()) { let kids = { tag: "text" , content: item.textContent, }; vnode.children.push(kids); } } else if (item.nodeType === Node.ELEMENT_NODE) { vnode.children.push(handleDom(item)); } } } return vnode; } return handleDom(jsContainer); }
相关知识点
题目描述
本题展示了一个简化版的标签输入框,功能如下: 1、当用户输入内容并敲回车键时,将输入框的内容在输入框前显示成标签,并清空输入框内容 2、当用户敲删除键时,如果输入框当前没有内容,则删除前一个标签 3、标签需要去掉字符串两端的多余的空格 4、标签不能为空字符串 5、标签不能重复,如果输入已存在的内容相同的标签,则不添加,并清空输入框 6、请补充完成tagInput.init、tagInput.bindEvent、tagInput.addTag、tagInput.removeTag函数,实现上面的需求 7、相关键码值,回车键=13,删除键=8 8、请不要手动修改html和css 9、不要使用第三方插件 10、请使用ES5语法
代码 .html:
1 2 3 4 5 6 7 <div class ="tag-input" > <span class ="tag" > 前端</span > <span class ="tag" > 编程题</span > <span class ="tag" > 示例</span > <span class ="tag" > 标签</span > <input type ="text" class ="js-input" maxlength ="6" placeholder ="请输入标签" > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 .tag-input { position : relative; border : 1px solid #cccccc ; padding : 0 5px ; display : flex; flex-flow : row wrap; } .js-input { width : 450px ; height : 22px ; line-height : 22px ; font-size : 16px ; padding : 0 ; margin : 5px 0 ; outline : none; border : none; width : 6.5em ; height : 24px ; line-height : 24px ; } .tag { padding : 0 10px ; margin : 5px 5px 5px 0 ; background : #25bb9b ; color : #ffffff ; height : 24px ; line-height : 24px ; border-radius : 12px ; font-size : 13px ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 var tagInput = { isInited: false , init: init, bindEvent: bindEvent, addTag: addTag, removeTag: removeTag, }; tagInput.init(); function init ( ) { var that = this ; if (that.isInited) return ; that.isInited = true ; that.input = document .getElementsByClassName("js-input" )[0 ]; that.bindEvent(); } function bindEvent ( ) { var that = this ; var input = that.input; if (!input) return ; input.addEventListener("keydown" , function (event ) { var isEnter = false ; if (event.keyCode === 13 ) isEnter = true ; var isDelete = false ; if (event.keyCode === 8 || !that.input.value) isDelete = true ; (isEnter || isDelete) && event.preventDefault(); isEnter && that.addTag(); isDelete && that.removeTag(); }); input.parentNode.addEventListener("click" , function ( ) { input.focus(); }); } function addTag ( ) { var that = this ; if (that.input.value === "" ) return ; var newSpan = document .createElement("span" ); newSpan.className = "tag" ; newSpan.innerHTML = that.input.value.trim(); var tagList = that.input.parentElement.innerText.split("\n" ); if (!tagList.includes(that.input.value)) { that.input.parentElement.insertBefore(newSpan, that.input); } that.input.value = "" ; } function removeTag ( ) { var that = this ; that.input.parentElement.removeChild(that.input.previousElementSibling); }
提交未通过,不过可以正常运行
相关知识点
监听键盘事件
重复元素判定
原生js函数DOM操作
题目描述 CheckGroup是一个选择组件类,支持单选和多选 选项参数格式、调用方式以及效果如下
选项参数格式:
1 var options = [{text : '选项a' , value : 'a' }, {text : '选项b' , value : 'b' }, {text : '选项c' , value : 'c' }, {text : '选项d' , value : 'd' }];
实例化单选组件:
1 2 var item = new CheckGroup(document .getElementById('jsCheckGroup' ), options);item.val(['a' ]);
实例化多选组件:
1 2 var item = new CheckGroup(document .getElementById('jsCheckGroup' ), options, true );item.val(['a' ]);
具体功能和需求如下: 1、单选组件请在 div.checkgroup 元素加上class radius 2、选中时,请在对应选项dom元素加上class selected 3、点击单选选项,如果未选中当前选项则选中当前选项并取消其他选项,否则取消当前选项 4、点击多选选项,如果未选中当前选项则选中当前选项,否则取消当前选项 5、给定的options中, text和value属性的值均为非空字符串 6、val方法的参数和返回值均为数组(单选时数组长度不超过) 7、请阅读代码,并根据注释完成对应代码(方法initHtml、toggleEl、isSelected、val) 8、请不要手动修改html和css 9、不要使用第三方插件
代码 .html:
1 2 3 4 5 6 7 8 <div id ="jsCheckGroup" > <div class ="checkgroup radius" > <div data-val ="a" class ="item selected" > 选项a</div > <div data-val ="b" class ="item" > 选项b</div > <div data-val ="c" class ="item" > 选项c</div > <div data-val ="d" class ="item" > 选项d</div > </div > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 .checkgroup .item { height : 42px ; line-height : 42px ; padding : 0 10px ; margin : 10px 0 ; border : 1px solid #c7c7c7 ; border-radius : 6px ; } .checkgroup .radius .item { border-radius : 21px ; } .checkgroup .item .selected { border : 1px solid #08b292 ; background : #08b292 ; color : #ffffff ; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 function CheckGroup (renderTo, options, isMultiple ) { var that = this ; that.renderTo = renderTo; that.options = options; that.isMultiple = !!isMultiple; that.initHtml(); that.initEvent(); } CheckGroup.prototype.initHtml = fInitHtml; CheckGroup.prototype.initEvent = fInitEvent; CheckGroup.prototype.toggleEl = fToggleEl; CheckGroup.prototype.isSelected = fIsSelected; CheckGroup.prototype.val = fVal; function fInitHtml ( ) { var that = this ; var sHtml = `<div class="checkgroup ' ' : ' radius'">` ; that, options.forEach((item ) => { sHtml += `<div data-val="${item.value} " class="item">${item.text} </div>` ; }); sHtml += "</div>" ; that.renderTo.innerHTML = sHtml; that.el = document .querySelector(".checkgroup" ); } function fInitEvent ( ) { var that = this ; that.el && that.el.addEventListener("click" , function (event ) { var item = event.target; item.classList.contains("item" ) && that.toggleEl(item); }); } function fToggleEl (item ) { var that = this ; if (that.isSelected(item)) { item.classList.remove("selected" ); that.val(); } else if (that.isMultiple) { item.classList.add("selected" ); that.val(); } else { let prevSelectedNode = [...item.parentElement.childNodes].find((el ) => that.isSelected(el) ); prevSelectedNode && prevSelectedNode.classList.remove("selected" ); item.classList.add("selected" ); that.val(); } } function fIsSelected (item ) { if ([...item.classList].includes("selected" )) return item; } function fVal (values ) { var that = this ; if (arguments .length === 0 ) { var items = [...that.renderTo.childNodes[0 ].childNodes].filter((el ) => [...el.classList].includes("selected" ) ); var result = items.map((el ) => el.dataset.val); return result; } !that.isMultiple && values.length > 1 && (values.length = 1 ); var items = that.renderTo.childNodes[0 ].childNodes; items.forEach((item ) => { if (values.includes(item.dataset.val)) { item.classList.add("selected" ); } }); }
执行之后内部错误
相关知识点
题目描述 本题展示了一个简化版的计算器,需求如下: 1、除法操作时,如果被除数为0,则结果为0 2、结果如果为小数,最多保留小数点后两位,如 2 / 3 = 0.67(显示0.67), 1 / 2 = 0.5(显示0.5) 3、请阅读并根据提示补充完成函数initEvent、result和calculate 4、请不要手动修改html和css 5、不要使用第三方插件
代码 .html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <div class ="calculator" > <header class ="cal-header" > 简易计算器</header > <main class ="cal-main" > <div class ="origin-value" > 0</div > <div class ="cal-keyboard" > <ul class ="cal-items" > <li data-action ="num" > 7</li > <li data-action ="num" > 8</li > <li data-action ="num" > 9</li > <li data-action ="operator" > ÷</li > <li data-action ="num" > 4</li > <li data-action ="num" > 5</li > <li data-action ="num" > 6</li > <li data-action ="operator" > x</li > <li data-action ="num" > 1</li > <li data-action ="num" > 2</li > <li data-action ="num" > 3</li > <li data-action ="operator" > -</li > <li data-action ="num" > 0</li > <li data-action ="operator" > 清空</li > <li data-action ="operator" > =</li > <li data-action ="operator" > +</li > </ul > </div > </main > </div >
.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 body ,ul ,li ,select { margin : 0 ; padding : 0 ; box-sizing : border-box; } ul ,li { list-style : none; } .calculator { max-width : 300px ; margin : 20px auto; border : 1px solid #eee ; border-radius : 3px ; } .cal-header { font-size : 16px ; color : #333 ; font-weight : bold; height : 48px ; line-height : 48px ; border-bottom : 1px solid #eee ; text-align : center; } .cal-main { font-size : 14px ; } .cal-main .origin-value { padding : 15px ; height : 40px ; line-height : 40px ; font-size : 20px ; text-align : right; overflow : hidden; text-overflow : ellipsis; white-space : nowrap; } .cal-main .origin-type ,.cal-main .target-type { padding-left : 5px ; width : 70px ; font-size : 14px ; height : 30px ; border : 1px solid #eee ; background-color : #fff ; vertical-align : middle; margin-right : 10px ; border-radius : 3px ; } .cal-keyboard { overflow : hidden; } .cal-items { overflow : hidden; } .cal-items li { user-select: none; float : left; display : inline-block; width : 75px ; height : 75px ; text-align : center; line-height : 75px ; border-top : 1px solid #eee ; border-left : 1px solid #eee ; box-sizing : border-box; } li :nth-of-type (4 n + 1 ) { border-left : none; } li [data-action="operator" ] { background : #f5923e ; color : #fff ; } .buttons { float : left; width : 75px ; } .buttons .btn { width : 75px ; background-color : #fff ; border-top : 1px solid #eee ; border-left : 1px solid #eee ; height : 150px ; line-height : 150px ; text-align : center; } .btn-esc { color : #ff5a34 ; } .btn-backspace { position : relative; }
.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 var Calculator = { init: function ( ) { var that = this ; if (!that.isInited) { that.isInited = true ; that.data = { total : 0 , next : "" , action : "" }; that.bindEvent(); } }, bindEvent: function ( ) { var that = this ; var keyboardEl = document .querySelector(".cal-keyboard" ); keyboardEl && keyboardEl.addEventListener("click" , function (event ) { var target = event.path[0 ]; var action = target.dataset.action; var value = target.innerText; if (action === "num" || action === "operator" ) { that.result(value, action === "num" ); } }); }, result: function (action, isNum ) { var that = this ; var data = that.data; if (isNum) { data.next = data.next === "0" ? action : data.next + action; !data.action && (data.total = 0 ); } else if (action === "清空" ) { data.total = 0 ; data.next = "" ; data.action = "" ; } else if (action === "=" ) { if (data.next || data.action) { data.total = that.calculate(data.total, data.next, data.action); data.next = "" ; data.action = "" ; } } else if (!data.next) { data.action = action; } else if (data.action) { data.total = that.calculate(data.total, data.next, data.action); data.next = "" ; data.action = action; } else { data.total = +data.next || 0 ; data.next = "" ; data.action = action; } var valEl = document .querySelector(".origin-value" ); valEl && (valEl.innerHTML = data.next || data.total || "0" ); }, calculate: function (n1, n2, operator ) { n1 = +n1 || 0 ; n2 = +n2 || 0 ; if (operator === "÷" ) { if (n2 === 0 ) return 0 ; return parse2Float(n1 / n2); } else if (operator === "x" ) { return parse2Float(n1 * n2); } else if (operator === "+" ) { return parse2Float(n1 + n2); } else if (operator === "-" ) { return parse2Float(n1 - n2); } }, }; function parse2Float (num ) { if (String (num).split("." )[1 ] && String (num).split("." )[1 ].length > 2 ) { num = num.toFixed(2 ); } return num; } Calculator.init();
相关知识点