1、为数组去重
方法一:双层for循环
思路:双层循环,外层循环元素,内层循环时进行比较,如果有相同的值则跳过,不相同则用push进新数组,然后返回新数组,因为它的时间复杂度是O(n^2),如果数组长度很大,效率会很低
Array.prototype.removeDuplicate=function(){
var arr=this,result=[],i,j,len=arr.length;
for(i=0;i<len;i++){
for(j=i+1;j<len;j++){
if(arr[i]===arr[j]){
j=++i
}
}
result.push(arr[i])
}
return result
}
方法二:Array.filter() 加 indexOf/includes
思路:利用indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等,如果不等则说明该元素是重复元素
function distinct(a, b) {
let arr = a.concat(b);
return arr.filter((item, index)=> {
return arr.includes(item)
})
}
方法三:ES6 中的 Set 去重
思路: ES6 提供了新的数据结构 Set,Set 结构的一个特性就是成员值都是唯一的,没有重复的值。
function distinct(array) {
return Array.from(new Set(array));
}
2、将一个setTimeout转为Promise
function sleep(ms){
return new Promise((resolve,reject)=>{
if(ms>1000)reject(new Error('延迟时间过长'))
setTimeout(()=>resolve(),ms)
})
}
3、求出所有参数中偶数之和,参数不定
function sumEven(){
var len=arguments.length;
if(len==0){
return 0
}
var sum=0;
for(var i=0;i<len;i++){
if(arguments[i]%2==0){
sum+=arguments[i]
}
return sum
}
}
4、实现一个自动生成ID函数,每次调用ID值加1
function getID(){
var n=0
return function(){
return n++;
}
}
5、添加合适的css属性,使div.inner可以相对div.outer垂直居中,其中div.inner的高度不定(写出三种)
1、弹性盒模型
display:flex;
justify-content:center;
align-items:center;
2、父级
display:flex;
子元素:
margin:auto
3、定位
父元素
position:relative
子元素
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
6、为了遍历对象添加迭代器,使之可以使用for...of遍历
function addIterator(obj){
if(Object.prototype.toString.call(obj) !== "[object Object]"){
return //非对象,不处理
}
if(obj[Symbol.iterator]){
return //避免重复添加
}
const it = Object.create(Object.getPrototypeOf(obj), {
[Symbol.iterator]: {
enumerable: false,
writable: false,
configurable: true,
value: function() {
const _this = this
//也可使用: keys = Object.getOwnPropertyNames(this)
const keys = Object.keys(this)
let index = 0
return {
next(){
return {
value: _this[keys[index++]],
done: index>keys.length
}
}
}
}
}
})
Object.setPrototypeOf(obj, it)
}
7、遍历一棵树
function flatTree(tree){
for(var i in tree){
this.expandedKeys.push(tree[i].label)
if(tree[i].children){
this.setName(tree[i].children)
}
}
}
8、实现一个重复执行的函数,返回的函数每次执行后可以重复执行fn函数times次,每次时间间隔wait毫秒
function repeat(fn, times, wait) {
return () => {
for (let i = 1; i <= times; i++) {
setTimeout(fn, i * wait)
}
}
}
9、实现一个JS函数柯里化
柯里化的定义:接收一部分参数,返回一个函数接收剩余参数,接收足够参数后,执行原函数。
有两种思路:
- 通过函数的
length属性,获取函数的形参个数,形参的个数就是所需的参数个数 - 在调用柯里化工具函数时,手动指定所需的参数个数
通用版
function curry(fn, args) {
var length = fn.length;
var args = args || [];
return function(){
newArgs = args.concat(Array.prototype.slice.call(arguments));
if (newArgs.length < length) {
return curry.call(this,fn,newArgs);
}else{
return fn.apply(this,newArgs);
}
}
}
ES6写法
const curry = (fn, arr = []) => (...args) => (
arg => arg.length === fn.length
? fn(...arg)
: curry(fn, arg)
)([...arr, ...args])
10、实现一个双向绑定
defineProperty 版本
// 数据
const data = {
text: 'default'
};
const input = document.getElementById('input');
const span = document.getElementById('span');
// 数据劫持
Object.defineProperty(data, 'text', {
// 数据变化 --> 修改视图
set(newVal) {
input.value = newVal;
span.innerHTML = newVal;
}
});
// 视图更改 --> 数据变化
input.addEventListener('keyup', function(e) {
data.text = e.target.value;
});
proxy 版本
// 数据
const data = {
text: 'default'
};
const input = document.getElementById('input');
const span = document.getElementById('span');
// 数据劫持
const handler = {
set(target, key, value) {
target[key] = value;
// 数据变化 --> 修改视图
input.value = value;
span.innerHTML = value;
return value;
}
};
const proxy = new Proxy(data, handler);
// 视图更改 --> 数据变化
input.addEventListener('keyup', function(e) {
proxy.text = e.target.value;
});