Array 有多少種常用方法
不改變array的方法
indexOf() 和lastIndexOf()
- indexof() : 返回元素在數(shù)組的第一次出現(xiàn)的索引彤侍,從0開始盏阶。若數(shù)組不存在該元素名斟,則返回-1砰盐。
var arr = [1, 2, 2];
arr.indexOf(1); //0
arr.indexOf(10); //-1
- lastIndexOf(): 返回元素在數(shù)組最后一次出現(xiàn)的索引,如果沒有出現(xiàn)則返回-1.
var arr = [1, 2, 2];
arr.lastIndexOf(2); //2
arr.lastIndexOf(10); //-1
slice()方法
與字符串的substring()方法一樣晃择,截取數(shù)組的一部分宫屠,返回一個(gè)新的數(shù)組浪蹂。
- slice(start)索引從start開始截取
var arr = [1, 2, 2, 5, 6];
arr.slice(2) // [2, 5, 6]
- slice(start,end)索引從start開始到索引end結(jié)束。通常创葡,接受2個(gè)參數(shù)作為一個(gè)左閉右開區(qū)間灿渴,即包括開始索引位置的元素胰舆,但不包括結(jié)束索引位置的元素缚窿。
var arr = [1, 2, 2, 5, 6];
arr.slice(1,3) // [2, 2]
- slice()沒有參數(shù)误续,則是復(fù)制整個(gè)數(shù)組蹋嵌。
var arr = [1, 2, 2, 5, 6];
arr.slice();
concat():合并數(shù)組栽烂。
把當(dāng)前的數(shù)組和另一個(gè)數(shù)組連接起來腺办,并返回一個(gè)新的數(shù)組怀喉。
- 方法的參數(shù)可以有多個(gè)磺送,也可以任意任意類型崇呵,數(shù)值域慷、字符串、布爾值弛针、數(shù)組削茁、對象 都可以茧跋,參數(shù)會(huì)被被添加到新的數(shù)組中。
var arr1 = [1, 2, 3,4,5,6];
var arr2 = ['a','b','c'];
var arr3 = arr1.concat(arr2);
arr3; //[1, 2, 3, 4, 5, 6, "a", "b", "c"]
- 注意粥烁,如果參數(shù)是數(shù)組, 會(huì)被拉平一次讨阻,即數(shù)組會(huì)被拆開來变勇,加入到新的數(shù)組中搀绣。具體看示例:
var arr1 = [1, 2, 3];
var arr2 = arr1.concat(66,'abc',true,[10,20],[30,[31,32]],{x:100});
arr2; //[1, 2, 3, 66, "abc", true, 10, 20, 30, [31,32], {x:100}]
join(): 轉(zhuǎn)成字符串。
它會(huì)把當(dāng)前Array的每個(gè)元素都用指定的字符串連接起來麻捻,然后返回連接后的字符串贸毕。
- 參數(shù)是用來指定連接的字符串。見示例代碼:
var arr = [1, 2, 3];
arr.join('*') //"1*2*3"
- 如果沒有指定參數(shù)寇僧,默認(rèn)是用 "," 連接摊腋。
var arr = [1, 2, 3];
arr.join() //"1,2,3"
toString(): 返回?cái)?shù)組的字符串形式
var arr = [1, 2, 3];
arr.toString() // "1,2,3"
valueOf():返回?cái)?shù)組本身
var arr = [1, 2, 3];
arr.valueOf() // [1, 2, 3]
map():
- 對數(shù)組的所有成員依次調(diào)用一個(gè)函數(shù)沸版,返回值是一個(gè)新數(shù)組。
arr.map(function(elem, index, arr) {
return elem * index;
});
//[0, 2, 6]
- map方法接受一個(gè)函數(shù)作為參數(shù),該函數(shù)調(diào)用時(shí)兴蒸,map方法會(huì)將其傳入3個(gè)參數(shù)视粮,分別是當(dāng)前成員、當(dāng)前位置和數(shù)組本身(后2個(gè)參數(shù)可選)橙凳。
arr.map(function(elem, index, arr) {
return elem * index;
});
//[0, 2, 6]
- map方法還可以接受第2個(gè)參數(shù)蕾殴,表示回調(diào)函數(shù)執(zhí)行時(shí)this所指向的對象。
forEach():
與map方法很相似痕惋,也是遍歷數(shù)組的所有成員议谷,執(zhí)行某種操作逼裆。注意:forEach方法一般沒有返回值
var arr = [1, 2, 3];
function log(element, index, array) {
console.log('[' + index + '] = ' + element);
}
arr.forEach(log);
// [0] = 1
// [1] = 2
// [2] = 3
filter(): 刪選
var arr = [1, 2, 3, 4, 5];
arr.filter(function (elem, index, arr) {
return index % 2 === 1;
});
//[2, 4]
some()和every()
類似“斷言”(assert)桐愉,用來判斷數(shù)組成員是否符合某種條件系洛。
- 接受一個(gè)函數(shù)作為參數(shù),所有數(shù)組成員依次執(zhí)行該函數(shù),返回一個(gè)布爾值。該函數(shù)接受三個(gè)參數(shù)贾费,依次是當(dāng)前位置的成員唱凯、當(dāng)前位置的序號和整個(gè)數(shù)組票从。
- some方法是只要有一個(gè)數(shù)組成員的返回值是true先馆,則整個(gè)some方法的返回值就是true仿野,否則false劣针。
var arr = [1, 2, 3, 4];
arr.some(function (elem, index, arr) {
return elem >= 3;
});
// true
- every方法則是所有數(shù)組成員的返回值都是true,才返回true,否則false链嘀。
var arr = [1, 2, 3, 4];
arr.every(function (elem, index, arr) {
return elem >= 3;
});
// false
- 注意务傲,對于空數(shù)組模孩,some方法返回false块茁,every方法返回true
reduce()和reduceRight():
依次處理數(shù)組的每個(gè)成員崎场,最終累計(jì)為一個(gè)值萍诱。
- reduce是從左到右處理(從第一個(gè)成員到最后一個(gè)成員)
arr = [1, 2, 3]
arr.reduce(function(x, y){
console.log(x, y)
return x + y;
});
// 1 2
// 3 3
// 6
- reduceRight則是從右到左處理(從最后一個(gè)成員到第一個(gè)成員)
rr.reduceRight(function(x, y){
console.log(x, y)
return x + y;
});
// 3 2
// 5 1
// 6
改變原數(shù)組的方法
push():
向數(shù)組的末尾添加若干元素退盯。返回值是改變后的數(shù)組長度墅垮。
var arr = [1, 2];
arr.push(3) ;// 3
arr; // [1, 2, 3]
arr.push('b','c'); //5
arr; //[1, 2, 3, "b", "c"]
arr.push([10,20]); //6
arr; //[1, 2, 3, "b", "c", [10,20]]
pop()
刪除數(shù)組最后一個(gè)元素牡肉。返回值是刪除的元素。
var arr =[1, 2, 3, "b", "c", [10,20]];
arr.pop(); //[10, 20]
arr; // [1, 2, 3, "b", "c"]
unshift()
向數(shù)組頭部添加若干元素击纬。返回值是改變后的數(shù)組長度。
var arr = [1, 2];
arr.unshift(3,4 ); //4
arr; // [3, 4, 1, 2]
shift()
刪除數(shù)組第一個(gè)元素。返回值是刪除的元素
var arr = ['a', 'b', 1, 2];
arr.shift(); //'a'
arr; //['b', 1, 2]
sort()
數(shù)組排序村怪。
- 默認(rèn)是將所有元素轉(zhuǎn)換成字符串介时,再按字符串Unicode碼點(diǎn)排序。返回值是新的數(shù)組俭正。
var arr = [1, 2, 12, 'a', 'b', 'ab', 'A', 'B']
arr.sort(); //[1, 12, 2, "A", "B", "a", "ab", "b"] 注意:12排在了2的前面
- 如果元素都是數(shù)字伸但,要按從小到大排序隔显,可以傳入一個(gè)回調(diào)函數(shù)作為參數(shù)萌业。
var arr = [1, 2, 12, 100]
arr.sort(function(a,b){
return a-b;
});
// [1, 2, 12, 100]
reverse():
顛倒數(shù)組中元素的位置
var arr = [1, 2, 12, 'a', 'b', 'ab', 'A', 'B'];
arr.reverse();
//["B", "A", "ab", "b", "a", 12, 2, 1]
array.splice()
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
- 參數(shù)
start 為開始的索引,deletecount 表示要移除的數(shù)組元素的個(gè)數(shù)。item 為要添加進(jìn)數(shù)組的元素
如果 deleteCount 大于 start 之后的元素的總數(shù)漂彤,則從 start 后面的元素都將被刪除(含第 start 位)乞娄。
如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是說显歧,如果它大于或者等于start之后的所有元素的數(shù)量)仪或,那么start之后數(shù)組的所有元素都會(huì)被刪除。
如果 deleteCount 是 0 或者負(fù)數(shù)士骤,則不移除元素范删。這種情況下,至少應(yīng)添加一個(gè)新元素
- 只刪除,不添加拷肌〉降可以傳入2個(gè)參數(shù):
var arr = ['Alibaba', 'Tencent', 'Baidu', 'XiaoMi', '360'];
// 從索引2開始刪除3個(gè)元素
arr.splice(2, 3); // 返回刪除的元素 ['Baidu', 'XiaoMi', '360']
arr; // ['Alibaba', 'Tencent']
- 只添加,不刪除旨巷。第2個(gè)參數(shù)設(shè)為0,即不刪除元素添忘。
arr.splice(2, 0, 'Toutiao', 'Meituan', 'Didi'); // 返回[],因?yàn)闆]有刪除任何元素
arr; //["Alibaba", "Tencent", "Toutiao", "Meituan", "Didi"]
- 先刪除若干元素采呐,然后在刪除的位置上在添加若干個(gè)元素。
var arr =["Alibaba", "Tencent", "Toutiao", "Meituan", "Didi"]
arr.splice(2,2,'Apple','Google'); //["Toutiao", "Meituan"]
arr; //["Alibaba", "Tencent", "Apple", "Google", "Didi"]
作用域與執(zhí)行上下文的區(qū)別
- 作用域分全局作用域和函數(shù)作用域搁骑,由于js沒有塊級作用域(es6里規(guī)定了塊級作用域斧吐,詳情可自行查看),函數(shù)作用域可以用于隔離變量仲器,不同作用域下同名變量不會(huì)有沖突的煤率。作用域只是一個(gè)“地盤”,作用域是一個(gè)抽象的概念乏冀,其中沒有變量蝶糯。要通過作用域?qū)?yīng)的執(zhí)行上下文環(huán)境來獲取變量的值。作用域中變量的值是在執(zhí)行過程中產(chǎn)生的確定的辆沦,而作用域卻是在函數(shù)創(chuàng)建時(shí)就確定了昼捍。
- 執(zhí)行全局代碼時(shí),會(huì)產(chǎn)生一個(gè)執(zhí)行上下文環(huán)境肢扯,每次調(diào)用函數(shù)都又會(huì)產(chǎn)生執(zhí)行上下文環(huán)境妒茬。當(dāng)函數(shù)調(diào)用完成時(shí),這個(gè)上下文環(huán)境以及其中的數(shù)據(jù)都會(huì)被消除(當(dāng)然了閉包并不會(huì)乖乖就范)鹃彻,處于活動(dòng)狀態(tài)的執(zhí)行上下文環(huán)境只有一個(gè)。
參考推薦: http://www.cnblogs.com/wangfupeng1988/p/3977924.html
this指向
參考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this(MDN)
函數(shù)的調(diào)用方式?jīng)Q定了this的值妻献。記住調(diào)用方式?jīng)Q定了this的值蛛株。this不能在執(zhí)行期間被賦值,并且在每次函數(shù)被調(diào)用時(shí)this的值也可能會(huì)不同育拨。
this 的定義:當(dāng)前執(zhí)行代碼的環(huán)境對象
this 值的幾種區(qū)分情況:
全局環(huán)境
無論是否在嚴(yán)格模式下谨履,在全局執(zhí)行環(huán)境中(在任何函數(shù)體外部)this 都指向全局對象。
// 在瀏覽器中, window 對象同時(shí)也是全局對象:
console.log(this === window); // true
a = 37;
console.log(window.a); // 37
this.b = "MDN";
console.log(window.b) // "MDN"
console.log(b) // "MDN"
函數(shù)(運(yùn)行內(nèi))環(huán)境
簡單調(diào)用:
- 非嚴(yán)格模式下绍载,this默認(rèn)指向全局對象
function f1(){
return this;
}
//在瀏覽器中:
f1() === window; //在瀏覽器中扶歪,全局對象是window
//在Node中:
f1() === global;
- 嚴(yán)格模式下震檩,this將會(huì)默認(rèn)為undefined。
function f2(){
"use strict"; // 這里是嚴(yán)格模式
return this;
}
f2() === undefined; // true
call/apply方法調(diào)用害捕,改變this的指向
call和apply 都可以傳遞參數(shù),call 是傳遞多個(gè)參數(shù)闷畸,而apply則傳數(shù)組傳遞參數(shù)尝盼。
// 將一個(gè)對象作為call和apply的第一個(gè)參數(shù),this會(huì)被綁定到這個(gè)對象佑菩。
var obj = {a: 'Custom'};
// 這個(gè)屬性是在global對象定義的盾沫。
var a = 'Global';
function whatsThis(arg) {
return this.a; // this的值取決于函數(shù)的調(diào)用方式
}
whatsThis(); // 'Global'
whatsThis.call(obj); // 'Custom'
whatsThis.apply(obj); // 'Custom'
bind方法裁赠,改變this的指向
ECMAScript 5 引入了 Function.prototype.bind,調(diào)用f.bind(someObject)會(huì)創(chuàng)建一個(gè)與f具有相同函數(shù)體和作用域的函數(shù)赴精,但是在這個(gè)新函數(shù)中佩捞,this將永久地被綁定到了bind的第一個(gè)參數(shù)(注意永久綁定到第一個(gè)參數(shù)上,也就是不管綁定多少次bind蕾哟,都是指向第一個(gè)參數(shù))一忱,無論這個(gè)函數(shù)是如何被調(diào)用的。
function f(){
return this.a;
}
var g = f.bind({a:"azerty"});
console.log(g()); // azerty
var h = g.bind({a:'yoo'}); // bind只生效一次渐苏!
console.log(h()); // azerty
var o = {a:37, f:f, g:g, h:h};
console.log(o.f(), o.g(), o.h()); // 37, azerty, azerty
箭頭函數(shù)掀潮,改變this指向
在箭頭函數(shù)中,this與封閉詞法環(huán)境的this保持一致琼富。在全局代碼中仪吧,它將被設(shè)置為全局對象:
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
重難點(diǎn):
// 創(chuàng)建一個(gè)含有bar方法的obj對象,
// bar返回一個(gè)函數(shù)鞠眉,
// 這個(gè)函數(shù)返回this薯鼠,
// 這個(gè)返回的函數(shù)是以箭頭函數(shù)創(chuàng)建的,
// 所以它的this被永久綁定到了它外層函數(shù)的this械蹋。
// bar的值可以在調(diào)用中設(shè)置出皇,這反過來又設(shè)置了返回函數(shù)的值。
var obj = {
bar: function() {
var x = (() => this);
return x;
}
};
// 作為obj對象的一個(gè)方法來調(diào)用bar哗戈,把它的this綁定到obj郊艘。
// 將返回的函數(shù)的引用賦值給fn。
var fn = obj.bar();
// 直接調(diào)用fn而不設(shè)置this唯咬,
// 通常(即不使用箭頭函數(shù)的情況)默認(rèn)為全局對象
// 若在嚴(yán)格模式則為undefined
console.log(fn() === obj); // true
// 但是注意纱注,如果你只是引用obj的方法,
// 而沒有調(diào)用它
var fn2 = obj.bar;
// 那么調(diào)用箭頭函數(shù)后胆胰,this指向window狞贱,因?yàn)樗鼜?bar 繼承了this。
console.log(fn2()() == window); // true
特別注意的是蜀涨,當(dāng)方法是對象里的屬性時(shí)瞎嬉,如果調(diào)用的不是方法 obj.bar()這種形式,而是obj.bar這種形式厚柳,后面再去調(diào)用的時(shí)候氧枣,前者的this指向當(dāng)前對象obj,而后者指向全局對象。根本原因是由于執(zhí)行的上下文不一樣導(dǎo)致的别垮,希望細(xì)細(xì)品味挑胸。
作為對象的方法
當(dāng)函數(shù)作為對象里的方法被調(diào)用時(shí),它們的 this 是調(diào)用該函數(shù)的對象宰闰。
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); // logs 37
請注意茬贵,這樣的行為簿透,根本不受函數(shù)定義方式或位置的影響。
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37
同樣解藻,this 的綁定只受最靠近的成員引用的影響老充。在下面的這個(gè)例子中,我們把一個(gè)方法g當(dāng)作對象o.b的函數(shù)調(diào)用螟左。在這次執(zhí)行期間啡浊,函數(shù)中的this將指向o.b。事實(shí)證明胶背,這與他是對象 o 的成員沒有多大關(guān)系巷嚣,最靠近的引用才是最重要的。
o.b = {g: independent, prop: 42};
console.log(o.b.g()); // 42
即this指向最后一個(gè)調(diào)用方法的對象
原型鏈中的 this
對于在對象原型鏈上某處定義的方法钳吟,同樣的概念也適用廷粒。如果該方法存在于一個(gè)對象的原型鏈上,那么this指向的是調(diào)用這個(gè)方法的對象红且,就像該方法在對象上一樣坝茎。
var o = {
f: function() {
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
此處p繼承自o,但是調(diào)用f()方法的是p,則this指向p
getter 與 setter 中的 this
再次,相同的概念也適用于當(dāng)函數(shù)在一個(gè) getter 或者 setter 中被調(diào)用暇番。用作 getter 或 setter 的函數(shù)都會(huì)把 this 綁定到設(shè)置或獲取屬性的對象嗤放。
function sum() {
return this.a + this.b + this.c;
}
var o = {
a: 1,
b: 2,
c: 3,
get average() {
return (this.a + this.b + this.c) / 3;
}
};
Object.defineProperty(o, 'sum', {
get: sum, enumerable: true, configurable: true});
console.log(o.average, o.sum); // logs 2, 6
作為構(gòu)造函數(shù)
當(dāng)一個(gè)函數(shù)用作構(gòu)造函數(shù)時(shí)(使用new關(guān)鍵字),它的this被綁定到正在構(gòu)造的新對象壁酬。
/*
* 構(gòu)造函數(shù)這樣工作:
*
* function MyConstructor(){
* // 函數(shù)實(shí)體寫在這里
* // 根據(jù)需要在this上創(chuàng)建屬性次酌,然后賦值給它們,比如:
* this.fum = "nom";
* // 等等...
*
* // 如果函數(shù)具有返回對象的return語句舆乔,
* // 則該對象將是 new 表達(dá)式的結(jié)果岳服。
* // 否則,表達(dá)式的結(jié)果是當(dāng)前綁定到 this 的對象蜕煌。
* //(即通撑哨澹看到的常見情況)诬留。
* }
*/
function C(){
this.a = 37;
}
var o = new C();
console.log(o.a); // logs 37
function C2(){
this.a = 37;
return {a:38};
}
o = new C2();
console.log(o.a); // logs 38
雖然構(gòu)造器返回的默認(rèn)值是this所指的那個(gè)對象斜纪,但它仍可以手動(dòng)返回其他的對象(如果返回值不是一個(gè)對象,則返回this對象)文兑。
淺拷貝與深拷貝
對象類型在賦值的過程中其實(shí)是復(fù)制了地址盒刚,從而會(huì)導(dǎo)致改變了一方其他也都被改變的情況。通常在開發(fā)中我們不希望出現(xiàn)這樣的問題绿贞,我們可以使用淺拷貝來解決這個(gè)情況因块。
let a = {
age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2
淺拷貝
Object.assign實(shí)現(xiàn)淺拷貝
很多人認(rèn)為這個(gè)函數(shù)是用來深拷貝的。其實(shí)并不是籍铁,Object.assign 只會(huì)拷貝所有的屬性值到新的對象中涡上,如果屬性值是對象的話趾断,拷貝的是地址,所以并不是深拷貝吩愧。
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
... 來實(shí)現(xiàn)淺拷貝
let a = {
age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1
通常淺拷貝就能解決大部分問題了芋酌,但是當(dāng)我們遇到如下情況就可能需要使用到深拷貝了
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = { ...a }
a.jobs.first = 'native'
console.log(b.jobs.first) // native
淺拷貝只解決了第一層的問題,如果接下去的值中還有對象的話雁佳,那么就又回到最開始的話題了脐帝,兩者享有相同的地址。要解決這個(gè)問題糖权,我們就得使用深拷貝了堵腹。
深拷貝
這個(gè)問題通常可以通過 JSON.parse(JSON.stringify(object)) 來解決星澳。
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
但是該方法也是有局限性的:
- 會(huì)忽略 undefined
- 會(huì)忽略 symbol
- 不能序列化函數(shù)
- 不能解決循環(huán)引用的對象
let obj = {
a: 1,
b: {
c: 2,
d: 3,
},
}
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
如果你有這么一個(gè)循環(huán)引用對象疚顷,你會(huì)發(fā)現(xiàn)并不能通過該方法實(shí)現(xiàn)深拷貝()
在遇到函數(shù)、 undefined 或者 symbol 的時(shí)候募判,該對象也不能正常的序列化
let a = {
age: undefined,
sex: Symbol('male'),
jobs: function() {},
name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}
上述情況中荡含,該方法會(huì)忽略掉函數(shù)和 undefined 。
深度拷貝的實(shí)現(xiàn)方法:
- 手寫簡單的深度拷貝
function deepClone(obj) {
function isObject(o) {
return (typeof o === 'object' || typeof o === 'function') && o !== null
}
if (!isObject(obj)) {
throw new Error('非對象')
}
let isArray = Array.isArray(obj)
let newObj = isArray ? [...obj] : { ...obj }
Reflect.ownKeys(newObj).forEach(key => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}
let obj = {
a: [1, 2, 3],
b: {
c: 2,
d: 3
}
}
let newObj = deepClone(obj)
newObj.b.c = 1
console.log(obj.b.c) // 2
- 使用Lodash庫的clone 與 cloneDeep方法届垫。
find與filter的區(qū)別
- find:(但只是返回)符合條件的第一項(xiàng)(單個(gè)元素)释液。當(dāng)找到符合回調(diào)函數(shù)過濾條件的第一個(gè)元素時(shí),它會(huì)立即停止往下的搜尋装处。不再遍歷整個(gè)數(shù)組误债。
- filter: 返回的是數(shù)組,返回所有符合要求的數(shù)組妄迁,會(huì)遍歷整個(gè)數(shù)組寝蹈。
js 作用域
- 作用域是指程序源代碼中定義變量的區(qū)域。
- 作用域規(guī)定了如何查找變量登淘,也就是確定當(dāng)前執(zhí)行代碼對變量的訪問權(quán)限箫老。
- JavaScript 采用詞法作用域(lexical scoping),也就是靜態(tài)作用域黔州。
靜態(tài)作用域與動(dòng)態(tài)作用域
- 因?yàn)?JavaScript 采用的是詞法作用域耍鬓,函數(shù)的作用域在函數(shù)定義的時(shí)候就決定了。
- 而與詞法作用域相對的是動(dòng)態(tài)作用域流妻,函數(shù)的作用域是在函數(shù)調(diào)用的時(shí)候才決定的牲蜀。
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar(); // 1
結(jié)果是1, 可能有人就會(huì)問了,為啥不是2啊绅这,怎么是1.那是因?yàn)閖avascript采用的詞法作用域涣达。則執(zhí)行這個(gè)過程是這樣的:
執(zhí)行 foo 函數(shù),先從 foo 函數(shù)內(nèi)部查找是否有局部變量 value,如果沒有度苔,就根據(jù)書寫的位置匆篓,查找上面一層的代碼,也就是 value 等于 1寇窑,所以結(jié)果會(huì)打印 1奕删。如果是動(dòng)態(tài)作用域,那就是2了疗认。
查找順序:1完残、就近查找,同一作用域找不到横漏,往上一層找谨设。2、就根據(jù)書寫的位置缎浇,查找上面一層的代碼扎拣。
再看個(gè)例子:
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
結(jié)果都是'local scope',遵循上面的查找規(guī)則就行。記住千萬不要和上下文混淆素跺,可能會(huì)是完全不一樣的結(jié)果二蓝。
原型鏈以及方法等
繼承關(guān)系
class語法糖的實(shí)現(xiàn)
redux中間件如何穿起來
數(shù)組的扁平化(原始的方式)
原生方法與合成方法的區(qū)別
箭頭函數(shù)與普通函數(shù)的區(qū)別
高階組件的兩種實(shí)現(xiàn)方式
節(jié)流、防抖具體實(shí)現(xiàn)(代碼實(shí)現(xiàn))
移動(dòng)端點(diǎn)擊事件300ms的延遲如何解決指厌。為什么會(huì)有這種情況刊愚。
react 16.4之后生命周期有哪些變化
setState 同步有哪些情況
fetch 如何實(shí)現(xiàn)時(shí)間等待超時(shí)
持續(xù)更新中。踩验。鸥诽。。