js 基礎(chǔ)面試題

Array 有多少種常用方法

不改變array的方法

indexOf() 和lastIndexOf()

  1. indexof() : 返回元素在數(shù)組的第一次出現(xiàn)的索引彤侍,從0開始盏阶。若數(shù)組不存在該元素名斟,則返回-1砰盐。
var arr = [1, 2, 2];
arr.indexOf(1); //0
arr.indexOf(10); //-1
  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ù)組浪蹂。

  1. slice(start)索引從start開始截取
var arr = [1, 2, 2, 5, 6];
arr.slice(2) // [2, 5, 6]
  1. 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]
  1. slice()沒有參數(shù)误续,則是復(fù)制整個(gè)數(shù)組蹋嵌。
var arr = [1, 2, 2, 5, 6];
arr.slice();

concat():合并數(shù)組栽烂。

把當(dāng)前的數(shù)組和另一個(gè)數(shù)組連接起來腺办,并返回一個(gè)新的數(shù)組怀喉。

  1. 方法的參數(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"]
  1. 注意粥烁,如果參數(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è)元素都用指定的字符串連接起來麻捻,然后返回連接后的字符串贸毕。

  1. 參數(shù)是用來指定連接的字符串。見示例代碼:
var arr = [1, 2, 3];
arr.join('*')   //"1*2*3"
  1. 如果沒有指定參數(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():

  1. 對數(shù)組的所有成員依次調(diào)用一個(gè)函數(shù)沸版,返回值是一個(gè)新數(shù)組。
arr.map(function(elem, index, arr) {
    return elem * index;
}); 
//[0, 2, 6]
  1. 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]
  1. 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ù)組成員是否符合某種條件系洛。

  1. 接受一個(gè)函數(shù)作為參數(shù),所有數(shù)組成員依次執(zhí)行該函數(shù),返回一個(gè)布爾值。該函數(shù)接受三個(gè)參數(shù)贾费,依次是當(dāng)前位置的成員唱凯、當(dāng)前位置的序號和整個(gè)數(shù)組票从。
  2. some方法是只要有一個(gè)數(shù)組成員的返回值是true先馆,則整個(gè)some方法的返回值就是true仿野,否則false劣针。
var arr = [1, 2, 3, 4];
arr.some(function (elem, index, arr) {
  return elem >= 3;
});
// true
  1. every方法則是所有數(shù)組成員的返回值都是true,才返回true,否則false链嘀。
var arr = [1, 2, 3, 4];
arr.every(function (elem, index, arr) {
  return elem >= 3;
});
// false
  1. 注意务傲,對于空數(shù)組模孩,some方法返回false块茁,every方法返回true

reduce()和reduceRight():

依次處理數(shù)組的每個(gè)成員崎场,最終累計(jì)為一個(gè)值萍诱。

  1. reduce是從左到右處理(從第一個(gè)成員到最后一個(gè)成員)
arr = [1, 2, 3]
arr.reduce(function(x, y){
  console.log(x, y)
  return x + y;
});
// 1 2
// 3 3
// 6
  1. 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ù)組排序村怪。

  1. 默認(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的前面
  1. 如果元素都是數(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è)新元素

  1. 只刪除,不添加拷肌〉降可以傳入2個(gè)參數(shù):
var arr = ['Alibaba', 'Tencent', 'Baidu', 'XiaoMi', '360'];

// 從索引2開始刪除3個(gè)元素
arr.splice(2, 3); // 返回刪除的元素 ['Baidu', 'XiaoMi', '360']
arr; // ['Alibaba', 'Tencent']
  1. 只添加,不刪除旨巷。第2個(gè)參數(shù)設(shè)為0,即不刪除元素添忘。
arr.splice(2, 0, 'Toutiao', 'Meituan', 'Didi'); // 返回[],因?yàn)闆]有刪除任何元素
arr; //["Alibaba", "Tencent", "Toutiao", "Meituan", "Didi"]
  1. 先刪除若干元素采呐,然后在刪除的位置上在添加若干個(gè)元素。
var  arr =["Alibaba", "Tencent", "Toutiao", "Meituan", "Didi"]
arr.splice(2,2,'Apple','Google');  //["Toutiao", "Meituan"]
arr; //["Alibaba", "Tencent", "Apple", "Google", "Didi"]

作用域與執(zhí)行上下文的區(qū)別

  1. 作用域分全局作用域和函數(shù)作用域搁骑,由于js沒有塊級作用域(es6里規(guī)定了塊級作用域斧吐,詳情可自行查看),函數(shù)作用域可以用于隔離變量仲器,不同作用域下同名變量不會(huì)有沖突的煤率。作用域只是一個(gè)“地盤”,作用域是一個(gè)抽象的概念乏冀,其中沒有變量蝶糯。要通過作用域?qū)?yīng)的執(zhí)行上下文環(huán)境來獲取變量的值。作用域中變量的值是在執(zhí)行過程中產(chǎn)生的確定的辆沦,而作用域卻是在函數(shù)創(chuàng)建時(shí)就確定了昼捍。
  2. 執(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)深拷貝()


image.png

在遇到函數(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ù)更新中。踩验。鸥诽。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末箕憾,一起剝皮案震驚了整個(gè)濱河市牡借,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袭异,老刑警劉巖钠龙,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異御铃,居然都是意外死亡碴里,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門畅买,熙熙樓的掌柜王于貴愁眉苦臉地迎上來并闲,“玉大人细睡,你說我怎么就攤上這事谷羞。” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵湃缎,是天一觀的道長犀填。 經(jīng)常有香客問我,道長嗓违,這世上最難降的妖魔是什么九巡? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮蹂季,結(jié)果婚禮上冕广,老公的妹妹穿的比我還像新娘。我一直安慰自己偿洁,他們只是感情好撒汉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涕滋,像睡著了一般睬辐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宾肺,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天溯饵,我揣著相機(jī)與錄音,去河邊找鬼锨用。 笑死丰刊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的增拥。 我是一名探鬼主播藻三,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼跪者!你這毒婦竟也來了棵帽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤渣玲,失蹤者是張志新(化名)和其女友劉穎逗概,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忘衍,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逾苫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枚钓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铅搓。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖搀捷,靈堂內(nèi)的尸體忽然破棺而出星掰,到底是詐尸還是另有隱情多望,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布氢烘,位于F島的核電站怀偷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏播玖。R本人自食惡果不足惜椎工,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜀踏。 院中可真熱鬧维蒙,春花似錦、人聲如沸果覆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽随静。三九已至八千,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燎猛,已是汗流浹背恋捆。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留重绷,地道東北人沸停。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像昭卓,于是被迫代替她去往敵國和親愤钾。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354