前端进阶

一、 数组操作方法

  1. js中数组的api整理
    首先列出所有的方法:
    join(), sort(), slice(), splice(), concat(), reverse(), push()+pop(), shift()+unshift(), forEach(), map(), some(), every(), filter(), reduce()+reduceRight(), indexOf()+lastIndexOf(),
    Array.form(), Array.of(), copyWithin(), find()+findIndex(), fill(), entries()+keys()+values(), includes()
    以下是详细介绍
    1.join()
    join(separator): 将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。(不改变原数组)
    var arr = [1,2,3,4];
    console.log(arr.join()); //1,2,3,4
    console.log(arr.join("/")); //1/2/3/4
    通过join()方法可以实现重复字符串,只需传入字符串以及重复的次数,就能返回重复后的字符串,函数如下:
    function repeatString(str, n) {
    return new Array(n + 1).join(str);
    }
    console.log(repeatString(“abc”, 3)); // abcabcabc
    2.sort()
    sort():按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。
    在排序时,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值, sort()方法比较的也是字符串,因此会出现以下的这种情况:
    var arr1 = [“d”, “a”, “c”, “b”];
    console.log(arr1.sort()); // [“a”, “b”, “c”, “d”]
    arr2 = [11, 24, 41, 3];
    console.log(arr2.sort()); // [11, 24, 3, 41]
    console.log(arr2); // 13, 24, 3, 51
    为了解决上述问题,sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数。以下就是一个简单的比较函数:
    function compare(a, b) {
    return a-b
    }
    arr2 = [11, 24, 41, 3];
    console.log(arr2.sort(compare)); // [3, 11, 24, 41]
    或者console.log(arr2.sort((a,b)=>{return a-b}));
    如果需要通过比较函数产生降序排序的结果,只要交换比较函数返回的值return b-a即可。
    3.slice()
    slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。

var arr = [1,3,5,7,9,11];var arrCopy = arr.slice(1);var arrCopy2 = arr.slice(1,4);var arrCopy3 = arr.slice(1,-2);var arrCopy4 = arr.slice(-4,-1);
console.log(arr); //1, 3, 5, 7, 9, 11
console.log(arrCopy); //[3, 5, 7, 9, 11]
console.log(arrCopy2); //[3, 5, 7]
console.log(arrCopy3); //[3, 5, 7]
console.log(arrCopy4); //[5, 7, 9]

arrCopy只设置了一个参数,也就是起始下标为1,所以返回的数组为下标1(包括下标1)开始到数组最后。
arrCopy2设置了两个参数,返回起始下标(包括1)开始到终止下标(不包括4)的子数组。
arrCopy3设置了两个参数,终止下标为负数,当出现负数时,将负数加上数组长度的值(6)来替换该位置的数,因此就是从1开始到4(不包括)的子数组。
arrCopy4中两个参数都是负数,所以都加上数组长度6转换成正数,因此相当于slice(2,5)。
4.splice()
splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。
删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。
splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组。

var arr = [1,3,5,7,9,11];var arrRemoved = arr.splice(0,2);
console.log(arr); //[5, 7, 9, 11]
console.log(arrRemoved); //[1, 3]var arrRemoved2 = arr.splice(2,0,4,6);
console.log(arr); // [5, 7, 4, 6, 9, 11]
console.log(arrRemoved2); // []var arrRemoved3 = arr.splice(1,1,2,4);
console.log(arr); // [5, 2, 4, 4, 6, 9, 11]
console.log(arrRemoved3); //[7]

5.concat()
concat() :将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。
var arr = [1,3,5,7];var arrCopy = arr.concat(9,[11,13]);
console.log(arrCopy); //[1, 3, 5, 7, 9, 11, 13]
console.log(arr); // 1, 3, 5, 7
从上面测试结果可以发现:传入的不是数组,则直接把参数添加到数组后面,如果传入的是数组,则将数组中的各个项添加到数组中。但是如果传入的是一个二维数组呢?
var arrCopy2 = arr.concat([9,[11,13]]);
console.log(arrCopy2); //[1, 3, 5, 7, 9, Array[2]]
console.log(arrCopy2[5]); //[11, 13]
上述代码中,arrCopy2数组的第五项是一个包含两项的数组,也就是说concat方法只能将传入数组中的每一项添加到数组中,如果传入数组中有些项是数组,那么也会把这一数组项当作一项添加到arrCopy2中。
6.reverse()
reverse():反转数组项的顺序。
var arr = [13, 24, 51, 3];
console.log(arr.reverse()); //[3, 51, 24, 13]
console.log(arr); //3, 51, 24, 13
7.push()+pop()
push(): 可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
pop():数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。

var arr = [“Lily”,“lucy”,“Tom”];var count = arr.push(“Jack”,“Sean”);
console.log(count); // 5
console.log(arr); // [“Lily”, “lucy”, “Tom”, “Jack”, “Sean”]var item = arr.pop();
console.log(item); // Sean
console.log(arr); // [“Lily”, “lucy”, “Tom”, “Jack”]

8.shift()+unshift()
shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
unshift:将参数添加到原数组开头,并返回数组的长度 。
这组方法和上面的push()和pop()方法正好对应,一个是操作数组的开头,一个是操作数组的结尾。

var arr = [“Lily”,“lucy”,“Tom”];var count = arr.unshift(“Jack”,“Sean”);
console.log(count); // 5
console.log(arr); //[“Jack”, “Sean”, “Lily”, “lucy”, “Tom”]var item = arr.shift();
console.log(item); // Jack
console.log(arr); // [“Sean”, “Lily”, “lucy”, “Tom”]

9.forEach()
forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;对应的数组索引,数组本身。

var arr = [1, 2, 3, 4, 5];
arr.forEach(function(item, index, array){
console.log(item + ‘-’ + index + ‘-’ + (array === arr));
});// 输出为:
//1-0-true
//2-1-true
//3-2-true
//4-3-true
//5-4-true

10.map()
map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
下面代码利用map方法实现数组中每个数求平方。
var arr = [1, 2, 3, 4, 5];var arr2 = arr.map(item => item*item);
console.log(arr2); //[1, 4, 9, 16, 25]
11.some()
some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
var arr = [1, 2, 3, 4, 5];var arr2 = arr.some(x => x<3);
console.log(arr2); //truevar arr3 = arr.some(x => x<1);
console.log(arr3); // false
12.every()
every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
var arr = [1, 2, 3, 4, 5];var arr2 = arr.every(x => x<10);
console.log(arr2); //truevar arr3 = arr.every(x => x<3);
console.log(arr3); // false
13.filter()
filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];var arr2 = arr.filter((item, index) => {
  return index % 3 === 0 || item >= 8;
});
console.log(arr2); //[1, 4, 7, 8, 9, 10]
14.reduce()+reduceRight()
这两个方法都会实现迭代数组的所有项,然后构建一个最终返回的值。reduce()方法从数组的第一项开始,逐个遍历到最后。而 reduceRight()则从数组的最后一项开始,向前遍历到第一项。
这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。
传给 reduce()和 reduceRight()的函数接收 4 个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。
下面代码用reduce()实现数组求和,数组一开始加了一个初始值10。
var values = [1,2,3,4,5];var sum = values.reduceRight((prev, cur, index, array) => {
return prev + cur;
},10);
console.log(sum); //25
15.indexOf()+lastIndexOf()
indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。
这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回1。在比较第一个参数与数组中的每一项时,会使用全等操作符。
var arr = [1,3,5,7,7,5,3,1];
console.log(arr.indexOf(5)); //2
console.log(arr.lastIndexOf(5)); //5
console.log(arr.indexOf(5,2)); //2
console.log(arr.lastIndexOf(5,4)); //2
console.log(arr.indexOf(“5”)); //-1
16.Array.form()
这个东西就是把一些集合,或者长的像数组的伪数组转换成真的数组,比如arguments,js选择器找到dom集合,
还有对象模拟的数组
var obj = {
  ‘0’ : 1,
  length : 1
}
Array.from(obj / arguments / 伪数组) //返回的是一个数组
[].slice.call(arguments, 0) //这种方式根from方法是一样的效果
//Array.from还有第二个参数,是一个回掉函数,功能类似map
Array.from( [1, 2, 3], item => item * 2 )
17.Array.of()
把参数合并成一个数组返回,如果参数为空,则返回一个空数组
Array.of(1,2,3,4,5);//[1,2,3,4,5]
18.copyWithin()
这个不常用,但是很有意思。
参数有3个,1:被替换的起始位置,2:选取替换值的起始位置,3:选取替换值的结束位置
var arr = [1, ‘c’, ‘d’, ‘a’, ‘b’]; //假如我想把a,b替换到1的位置
arr.copyWithin(0, 3, 5) // [“a”, “b”, “d”, “a”, “b”]
19.find()+findIndex()
返回数组中第一个符合条件的元素,findIndex返回索引
[1, 2, 3, 4, 5].find((item) => {return item > 3}) //4
20.fill()
功能一:字面意思填满,实际功能就是把数组中的每一个元素替换成指定值
功能二:指定范围替换,第一个参数替换值,第二个是起始下标,第三个结束下标(不包含)
功能三:扩展对象
var arr = [1, 2, 3, 4]
arr.fill(5); //[5,5,5,5]
arr.fill(6,1,3); //[1,6,6,5]
[].fill.call({length:3},4); //{0:4,1:4,2:4}
21.entries/keys/values
都取/取键/取值
var arr=[‘a’, ‘b’, ‘c’]for(let key of arr.keys()){console.log(key)} //0,1,2 for(let value of arr.values()){console.log(value)} //a,b,c for(let [key, value] of arr.entries()){console.log([key,value])} //[0,‘a’],[1,‘b’],[2,‘c’]
22.includes
判断数组是否包含某项,返回true/false
[1, 2, 3, 4, 5].includes(4) //true
[1, 2, 3, 4, NaN].includes(NaN) //true

二 vue点击添加生成多个表单,v-model互不影响方法
1 在数组 arr =[],点击添加时arr.push({val:’’}),页面上v-for=”item of arr”遍历数组,
v-model=“item.val”即可

Vue普通table加选择框方案:每次点击获得一个item,对比item即可

Vue中根据第一个select值发送请求获取第二个select值:
关于2个select值级联问题,可以监听第一个select值的变化再给第二个select的option

二 Git无法clone问题
Git clone http://用户名@git…地址即可

三Axios同步异步问题解决
2. 使用 asyns/await 将 axios 异步请求同步化:
2.1 当 axios 请求拿到的数据在不同场景下做相同的处理时:
export default {
name: ‘Historys’,
data() {
return {
totalData: 0,
tableData: []
}
},
created () {
this.getHistoryData()
},
methods: {
handleClick (tab) {
let data = {
status: tab.name,
name: this.formInline.user,
cid: this.formInline.identity,
start_time: this.formInline.dateTime ? this.formInline.dateTime[0] : ‘’,
end_time: this.formInline.dateTime ? this.formInline.dateTime[1] : ‘’
}
this.getHistoryData()
},
// 统一处理axios请求
async getHistoryData (data) {
try {
let res = await axios.get(’/api/survey/list/’, {
params: data
})
this.tableData = res.data.result
this.totalData = res.data.count
} catch (err) {
console.log(err)
alert(‘请求出错!’)
}
}
}
}
2.2 当 axios 请求拿到的数据在不同场景下做不同的处理时:
export default {
name: ‘Historys’,
data() {
return {
totalData: 0,
tableData: []
}
},
async created () {
try {
let res = await this.getHistoryData()
console.log(res)
// 等拿到返回数据res后再进行处理
this.tableData = res.data.result
this.totalData = res.data.count
} catch (err) {
console.log(err)
alert(‘请求出错’)
}
},
methods: {
async handleClick (tab) {
let data = {
status: tab.name,
name: this.formInline.user,
cid: this.formInline.identity,
start_time: this.formInline.dateTime ? this.formInline.dateTime[0] : ‘’,
end_time: this.formInline.dateTime ? this.formInline.dateTime[1] : ‘’
}
try {
let res = await this.getHistoryData()
console.log(res)
// 等拿到返回数据res后再进行处理
this.tableData = res.data.result
this.totalData = res.data.count
} catch (err) {
console.log(err)
alert(‘请求出错’)
}
},
// 封装axios请求,返回promise, 用于调用getHistoryData函数后作不同处理
getHistoryData (data) {
return new Promise((resolve, reject) => {
axios.get(’/api/survey/list/’, {
params: data
}).then((res) => {
resolve(res)
}).catch((err) => {
reject(err)
})
})
}
}
}
四 New promise 原理
1 改变状态
https://blog.csdn.net/weixin_41436338/article/details/79806033
1.1 最终实例
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(‘FULFILLED’)
}, 1000)})

1.2 代码设计
class MyPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error(‘MyPromise must accept a function as a parameter’)
}
// 添加状态
this._status = PENDING
// 添加状态
this._value = undefined
// 执行handle
try {
handle(this._resolve.bind(this), this._reject.bind(this)) //传递函数,但要调用函数才能使用
} catch (err) {
this._reject(err)
}
}
// 添加resovle时执行的函数
_resolve (val) {
if (this._status !== PENDING) return
this._status = FULFILLED
this._value = val
}
// 添加reject时执行的函数
_reject (err) {
if (this._status !== PENDING) return
this._status = REJECTED
this._value = err
}}

Elementui单选方法:


<el-radio :label=“scope. i n d e x " v − m o d e l = " t e m p l a t e R a d i o " @ c h a n g e . n a t i v e = " g e t T e m p l a t e R o w ( s c o p e . index" v-model="templateRadio" @change.native="getTemplateRow(scope. index"vmodel="templateRadio"@change.native="getTemplateRow(scope.index,scope.row)”> 

五 宏任务与微任务
事件运行顺序
1.执行同步任务,同步任务不需要做特殊处理,直接执行(下面的步骤中遇到同步任务都是一样处理) — 第一轮从 script开始
2.从宏任务队列中取出队头任务执行
3.如果产生了宏任务,将宏任务放入宏任务队列,下次轮循的时候执行
4.如果产生了微任务,将微任务放入微任务队列
5.执行完当前宏任务之后,取出微任务队列中的所有任务依次执行
6.如果微任务执行过程中产生了新的微任务,则继续执行微任务,直到微任务的队列为空
7.轮循,循环以上 2 - 6

比如排队,你去营业厅办一个业务会有一个排队号码,当叫到你的号码的时候你去窗口办充值业务(宏任务执行),在你办理充值的时候你又想改个套餐(微任务),这个时候工作人员会直接帮你办,不可能让你重新排队,
Js执行时遇到宏任务先把宏任务加到队列,先执行完主线程的同步任务,即普通代码那些,再执行一个宏任务中的所有代码包括微任务,再去执行下一个宏任务
2 例如:

  • console.log(‘script start’)
  • setTimeout(function() {
  • console.log(‘setTimeout’)
  • }, 0)
  • new Promise((resolve, reject)=>{
  • console.log(“promise1”)
  • resolve()
  • })
  • .then(()=>{
  • console.log(“then11”)
  • new Promise((resolve, reject)=>{
  •  console.log("promise2")
    
  •  resolve();
    
  • })
  • .then(() => {
  •  console.log("then2-1")
    
  • })
  • .then(() => {
  •  console.log("then2-2")
    
  • })
  • })
  • .then(()=>{
  • console.log(“then12”)
  • })
  • console.log(‘script end’)
    1.首先遇到 console.log(),输出 script start
    2.遇到 setTimeout 产生宏任务,注册到宏任务队列[setTimeout],下一轮 Event Loop 的时候在执行
    3.然后遇到 new Promise 构造声明(同步),log 输出 promise1,然后 resolve
    4.resolve 匹配到 promise1 的第一个 then,把这个 then 注册到微任务队列[then11]中,继续当前整体脚本的执行
    5.遇到最后的一个 log,输出 script end,当前执行栈清空
    6.从微任务队列中取出队头任务’then11’ 进行执行,其中有一个 log,输出 then11
    7.往下遇到 new Promise 构造声明(同步),log 输出 promise2,然后 resolve
    8.resolve 匹配到 promise2 的第一个 then,把这个 then 注册到微任务队列[then2-1],当前 then11 可执行部分结束,然后产生了 promise1 的第二个 then,把这个 then 注册到微任务队列[then2-1, then12]
    9.拿出微任务队头任务’then2-1’ 执行,log 输出 then2-1,触发 promise2 的第二个 then,注册到微任务队列[then12, then2-2]
    10.拿出微任务队头任务’then12’,log 输出 then12
    11.拿出微任务队头任务’then2-2’,log 输出 then2-2
    12.微任务队列执行完毕,别忘了宏任务队列中的 setTimeout,log 输出 setTimeout
    经过以上一番缜(xia)密(gao)分析,希望没有绕晕你,最后的输出结果就是:
    script start -> promise1 -> script end -> then11 -> promise2 -> then2-1 -> then12 -> then2-2 -> setTimeout

3 定义
宏任务
文章最开始的时候说过,在 chrome 里,每个页面都对应一个进程。而该进程又有多个线程,比如 JS 线程、渲染线程、IO 线程、网络线程、定时器线程等等,这些线程之间的通信是通过向对象的任务队列中添加一个任务(postTask)来实现的。宏任务的本质可以认为是多线程事件循环或消息循环,也就是线程间通信的一个消息队列。
就拿 setTimeout 举例来说,当遇到它的时候,浏览器就会对 Event Loop 说:嘿,我有一个任务交给你,Event Loop 就会说:好的,我会把它加到我的 todoList 中,之后我会执行它,它是需要调用 API 的。
宏任务的真面目是浏览器派发,与 JS 引擎无关的,参与了 Event Loop 调度的任务
微任务
微任务是在运行宏任务/同步任务的时候产生的,是属于当前任务的,所以它不需要浏览器的支持,内置在 JS 当中,直接在 JS 的引擎中就被执行掉了。

六 网易学习方向
1 图片

2 js进阶版本
2.1 高阶函数的使用
https://www.cnblogs.com/aimeeblogs/p/11855293.html

JavaScript设计模式与开发实践 pdf
2.1.1 call和apply

假如该事件函数中有一个内部函数 func,在事件内部调用 func 函数时,func 函数体内的 this
就指向了 window,而不是我们预期的 div,见如下代码:
document.getElementById( ‘div1’ ).onclick = function(){
alert( this.id ); // 输出:div1
var func = function(){
alert ( this.id ); // 输出:undefined
}
func();
};
这时候我们用 call 来修正 func 函数内的 this,使其依然指向 div:
document.getElementById( ‘div1’ ).onclick = function(){
var func = function(){
alert ( this.id ); // 输出:div1
}
func.call( this );
};
2.1.2 判断类型
var isType = function( type ){
return function( obj ){
return Object.prototype.toString.call( obj ) === ‘[object ‘+ type +’]’;
}
};
2.1.3 节流
var throttle = function ( fn, interval ) {
var __self = fn, // 保存需要被延迟执行的函数引用
timer, // 定时器
firstTime = true; // 是否是第一次调用
return function () {
var args = arguments,
__me = this;
if ( firstTime ) { // 如果是第一次调用,不需延迟执行
__self.apply(__me, args);
return firstTime = false;
}
if ( timer ) { // 如果定时器还在,说明前一次延迟执行还没有完成
return false;
}
timer = setTimeout(function () { // 延迟一段时间执行
clearTimeout(timer);
timer = null;
__self.apply(__me, args);
}, interval || 500 );
};
};
window.onresize = throttle(function(){
console.log( 1 );
}, 500 );
2.1.4分时函数
见 书籍: javascript设计模式和开发实践 3.2.3
var timeChunk = function( ary, fn, count ){
var obj,
t;
var len = ary.length;
var start = function(){
for ( var i = 0; i < Math.min( count || 1, ary.length ); i++ ){
var obj = ary.shift();
fn( obj );
}
};
return function(){
t = setInterval(function(){
if ( ary.length === 0 ){ // 如果全部节点都已经被创建好
return clearInterval( t );
}
start();
}, 200 ); // 分批执行的时间间隔,也可以用参数的形式传入
};
};

2.2 compose https://blog.csdn.net/shi_Avicii/article/details/104282158
https://www.cnblogs.com/dennisj/p/12176290.html
2.2.1
const compose = function(){ // 将接收的参数存到一个数组, args == [multiply, add]
const args = [].slice.apply(arguments);
return function(x) {
return args.reduceRight((res, cb) => cb(res), x); } //x即为res的初始值
} // 我们来验证下这个方法
let calculate = compose(multiply, add);
let res = calculate(10); console.log(res);
2.2.2 args.reduceRight 理解
[0, 1, 2, 3, 4].reduceRight(function(previousValue, currentValue, index, array) {
console.log(previousValue) //即为1
return previousValue + currentValue;
}, 1);
2.3 PIPE函数
const pipe = function(){
const args = [].slice.apply(arguments);
return function(x) { return args.reduce((res, cb) => cb(res), x); } } // 参数顺序改为从左往右
let calculate = pipe(add, multiply);
let res = calculate(10); console.log(res); // 结果还是200
2.4常用函数
https://www.cnblogs.com/wakbook/p/11551242.html
https://www.jb51.net/article/159785.htm
2.5深拷贝
function deepClone(obj) {
//debugger
function isClass(o) {
//debugger
if (o === null) return “Null”;
if (o === undefined) return “Undefined”;
return Object.prototype.toString.call(o).slice(8, -1);
}
var result;
var oClass = isClass(obj);
if (oClass === “Object”) {
result = {};
} else if (oClass === “Array”) {
result = [];
} else {
return obj;
}
for (var key in obj) {
var copy = obj[key];
if (isClass(copy) == “Object”) {
result[key] = arguments.callee(copy);//递归调用
} else if (isClass(copy) == “Array”) {
result[key] = arguments.callee(copy);
} else {
result[key] = obj[key];
}
}
return result;
}
var a = {a:“1”,b:{c:[{a:“100”}]}}
b = deepClone(a)
2.6 js设计模式
https://www.cnblogs.com/wuguanglin/p/JavaScriptPattern.html

Github:

https://github.com/14glwu/FEInterviewBox/tree/master/JS%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F

用策略模式代替 if…else这些判断条件

七 前端插件类
1 视频插件 flvjs
2 桌面应用:electron
2.1 https://juejin.im/post/5ea2e21651882573bc7c3045
2.2 实例
https://github.com/SimulatedGREG/electron-vue

八设计模式笔记疑答
1 发布订阅模式
1.1代码数组解释
salesOffices.trigger = function(){ // 发布消息
var key = Array.prototype.shift.call( arguments ), // 取出消息类型
fns = this.clientList[ key ]; // 取出该消息对应的回调函数集合
if ( !fns || fns.length === 0 ){ // 如果没有订阅该消息,则返回
return false;
}
for( var i = 0, fn; fn = fns[ i++ ]; ){
fn.apply( this, arguments ); // (2) // arguments 是发布消息时附送的参数
}
};
注意:红色部分意思是把arguments转化为数组并获取第一个值
详解:https://blog.csdn.net/qq_27626333/article/details/51831282

      九 文档合集

1 地址 http://caibaojian.com/
2 excel前端下载 纯前端
JSONToExcelConvertor(JSONData, FileName) {
//先转化json
var arrData =
typeof JSONData != ‘object’ ? JSON.parse(JSONData) : JSONData
var excel = ‘


var row = ‘’
//设置表头
var keys = Object.keys(JSONData[0])
keys.forEach(function(item) {
row += ‘’
})
//换行
excel += row + ‘’
//设置数据
for (var i = 0; i < arrData.length; i++) {
var row = ‘’
for (var index in arrData[i]) {
console.log(arrData[i][index])
//var value = arrData[i][index] === “.” ? “” : arrData[i][index];
row += ‘’
}
excel += row + ‘’
}
’ + item + ‘
’ + arrData[i][index] + ‘

  excel += '</table>'

  var excelFile =
    "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>"
  excelFile +=
    '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'
  excelFile +=
    '<meta http-equiv="content-type" content="application/vnd.ms-excel'
  excelFile += '; charset=UTF-8">'
  excelFile += '<head>'
  excelFile += '<!--[if gte mso 9]>'
  excelFile += '<xml>'
  excelFile += '<x:ExcelWorkbook>'
  excelFile += '<x:ExcelWorksheets>'
  excelFile += '<x:ExcelWorksheet>'
  excelFile += '<x:Name>'
  excelFile += '{worksheet}'
  excelFile += '</x:Name>'
  excelFile += '<x:WorksheetOptions>'
  excelFile += '<x:DisplayGridlines/>'
  excelFile += '</x:WorksheetOptions>'
  excelFile += '</x:ExcelWorksheet>'
  excelFile += '</x:ExcelWorksheets>'
  excelFile += '</x:ExcelWorkbook>'
  excelFile += '</xml>'
  excelFile += '<![endif]-->'
  excelFile += '</head>'
  excelFile += '<body>'
  excelFile += excel
  excelFile += '</body>'
  excelFile += '</html>'

  var uri =
    'data:application/vnd.ms-excel;charset=utf-8,' +
    encodeURIComponent(excelFile)

  var link = document.createElement('a')
  link.href = uri

  link.style = 'visibility:hidden'
  link.download = FileName + '.xls'

  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

标题 前端进阶之路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值