前端學習的摘錄,持續更新中...
① 使用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"]
深度遍歷屬性值拷貝app
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)); }
length
屬性函數length
屬性的含義: 該函數預期傳入的參數個數。指定了默認值之後,length
將返回沒有指定默認值的參數個數;指定了默認值後,length屬性將失真。學習
(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2
若是設置了默認值的參數不是尾參數,那麼length屬性也再也不計入後面的參數了。this
(function (a = 0, b, c) {}).length // 0 (function (a, b = 1, c) {}).length // 1
若是參數默認值是一個變量,則該變量所處的做用域,與其餘變量的做用域規則是樣,即先是當前函數的做用域,而後纔是全局做用域。code
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。
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); }
JavaScript是詞法做用域不是動態做用域,詞法做用域是寫代碼或說定義時肯定的,動態做用域是在運行時肯定的,詞法做用域關注函數在何處申明,動態做用域關注在何處調用。可是,JS中的this
關注的也是函數的調用。
function foo() { console.log(a); // 2 } function bar () { var a = 3; foo(); } var a = 2; bar()
若是按照動態做用域理論運行結果是:3