前端进修的摘录,延续更新中…
1. 数组去重3种计划
① 运用set
去重:set是ES6中供应的数据结构,差别于数组,一切的值都是不反复的,Set内部运用===来推断是不是相称,相似’1’和1会两个都保留,NaN和NaN只会保留一个
let unique= [...new Set([1,'1',1,NaN,NaN,undefined,undefined,null,null])];
//[1, "1", NaN, undefined, null]
② 遍历,将值增加到新数组,用indexOf()推断值是不是存在,已存在就不增加,到达去重效果。(对NaN去重失利
)
let a = [1,'1',1,NaN,NaN,undefined,undefined,null,null];
let unique = arr =>{
let newA = [];
arr.forEach(key => {
if(newA.indexOf(key)<0){ //遍历newA是不是存在key,假如存在key会大于0就跳过push的那一步
newA.push(key);
}
});
return newA;
}
unique(a); // ["1", 1, NaN, NaN, undefined, null]
③ 遍历,将数组的值增加到一个对象的属性名里,并给属性赋值。对象不能增加雷同属性名,以这个为根据能够完成数组去重,然后用Object.keys(对象)
返回这个对象可罗列属性构成的数组,这个数组就是去重后的数组。(返回的都是字符串,关于1和'1'都当做'1'
)
let a = [1,'1',1,NaN,NaN,undefined,undefined,null,null];
let unique = arr => {
var obj = {};
arr.forEach(value => {
obj[value] = 0; // 随意赋值,为了将属性增加进obj对象
});
return Object.keys(obj);
}
unique(a); // ["1", "NaN", "undefined", "null"]
2. 深拷贝
深度遍历属性值拷贝
function deepcopy(obj) {
var copyObj = Object.create(Object.getPrototypeOf(obj));
Object.getOwnPropertyNames(obj).forEach((keyName) => {
if ( typeof obj[keyName] == 'object') {
copyObj[keyName] = deepcopy(obj[keyName])
} else {
copyObj[keyName] = obj[keyName]
}
});
return copyObj;
}
采纳JSON.parse(JSON.stringify(obj))
,有局限性
function deepcopy(obj){
return JSON.parse(JSON.stringify(obj));
}
3. 函数length
属性
函数length
属性的寄义: 该函数预期传入的参数个数。指定了默认值今后,length
将返回没有指定默认值的参数个数;指定了默认值后,length属性将失真。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
假如设置了默认值的参数不是尾参数,那末length属性也不再计入背面的参数了。
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
4.参数作用域
假如参数默认值是一个变量,则该变量所处的作用域,与其他变量的作用域规则是样,即先是当前函数的作用域,然后才是全局作用域。
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
上面代码中,参数y的默认值即是x。挪用时,因为函数作用域内部的变量x已天生,所以y即是参数x,而不是全局变量x;假如挪用时,函数作用域内部的变量x没有天生,效果则差别。
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
上面代码中,函数挪用时,y的默认值变量x尚未在函数内部天生,所以x指向全局变量。假如此时,全局变量x不存在,就会报错:ReferenceError: x is not defined
一个庞杂的例子:
var x = 1;
function foo(x, y = function() { x = 2; }) {
var x = 3;
y();
console.log(x);
}
foo() // 3
上面代码中,函数foo的参数y的默认值是一个匿名函数。函数foo挪用时,它的参数x的值为undefined,所以y函数内部的x一开始是undefined,厥后被从新赋值2。函数foo内部从新声清楚明了一个x,值为3,这两个x是不一样的,相互不产生影响,因而末了输出3。
假如将var x = 3的var去除,两个x就是一样的,末了输出的就是2。
5. call要领完成继续(apply雷同)
call的简朴运用:obj1.method.call(obj2,argument1,argument2,...)
, 用对象obj2替代当前对象obj1,假如obj2为空,则为全局对象。简朴运用:
function add(a, b) { return a+b; }
function sub(a, b) { return a-b; }
add.call(sub, 3, 1); // 4
继续:
function Parent() {
this.showMsg = function(msg) {
return msg;
}
}
function Child() {
Parent.call(this); // this.super()意味
}
const chi = new Child();
chi.showMsg('hello world'); // 'hello world'
多重继续:
function Parent1() {
this.add = function(a, b) {
return a + b;
}
}
function Parent2() {
this.sub = function(a, b) {
return a - b;
}
}
function Child() {
Parent1.call(this);
Parent2.call(this);
}
6. Javascript 词法作用域
JavaScript是词法作用域不是动态作用域,词法作用域是写代码或说定义时肯定的,动态作用域是在运转时肯定的,词法作用域关注函数在那边说明,动态作用域关注在那边挪用。然则,JS中的this
关注的也是函数的挪用。
function foo() {
console.log(a); // 2
}
function bar () {
var a = 3;
foo();
}
var a = 2;
bar()
假如根据动态作用域理论运转效果是:3