js(二)

1. IE 和 DOM 事件流的區(qū)別

1.事件流的區(qū)別
IE 采用冒泡型事件 Netscape 使用捕獲型事件
DOM 使用先捕獲后冒泡型事件
示例:

?body?
  ?div?
    ?button?點(diǎn)擊這里?/button?
  ?/div?
?/body?

冒泡型事件模型: button-?div-?body (IE 事件流)
捕獲型事件模型: body-?div-?button (Netscape 事件流)
DOM 事件模型: body-?div-?button-?button-?div-?body (先捕獲后冒泡)

2.事件偵聽函數(shù)的區(qū)別
IE 使用:

[Object].attachEvent("name_of_event_handler", fnHandler); //綁定函數(shù)
[Object].detachEvent("name_of_event_handler", fnHandler); //移除綁定

DOM 使用:

[Object].addEventListener("name_of_event", fnHandler, bCapture); //綁定函數(shù)
[Object].removeEventListener("name_of_event", fnHandler, bCapture);

//移除綁定bCapture 參數(shù)用于設(shè)置事件綁定的階段荆烈,true 為捕獲階段拯勉,false 為冒泡階段竟趾。

2.變量提升

js 代碼執(zhí)行的過(guò)程
變量提升
代碼從上到下依次執(zhí)行
var 關(guān)鍵字和 function 關(guān)鍵字聲明的變量會(huì)進(jìn)行變量提升
變量提升發(fā)生的環(huán)境:
發(fā)生在代碼所處的當(dāng)前作用域。
變量提升

var 關(guān)鍵字進(jìn)行的變量提升宫峦,會(huì)把變量提前聲明岔帽,但是不會(huì)提前賦值 。
function 關(guān)鍵字對(duì)變量進(jìn)行變量提升导绷,既會(huì)把變量提前聲明犀勒,又會(huì)把變量提前賦值,也就是把整個(gè)函數(shù)體提升到代碼的頂部
有一些代碼是不會(huì)執(zhí)行的但是仍舊會(huì)發(fā)生變量提升,規(guī)則適用于 1,2
return 之后的代碼依舊會(huì)發(fā)生變量提升妥曲,規(guī)則適用于 1贾费,2
代碼報(bào)錯(cuò)之后的代碼依舊會(huì)發(fā)生變量提升,規(guī)則適用于 1檐盟,2
break 之后的代碼依舊會(huì)發(fā)生變量提升褂萧,規(guī)則適用于 1,2
有一些代碼是不會(huì)執(zhí)行但是仍舊會(huì)發(fā)生變量提升,但是規(guī)則要發(fā)生變化
if 判斷語(yǔ)句 if 判斷語(yǔ)句中 var 關(guān)鍵字以及 function 關(guān)鍵字聲明的變量只會(huì)發(fā)生提前聲明葵萎,不會(huì)發(fā)生提前賦值,也就是不會(huì)吧函數(shù)體整體提升到當(dāng)前作用域頂部导犹。規(guī)則跟 1,2 不適用
switch case 規(guī)則跟 1,2 不適用
3 do while 規(guī)則跟 1,2 不適用
try catch catch 中聲明的變量只會(huì)發(fā)生提前聲明,不會(huì)發(fā)生提前賦值羡忘。
在條件判斷語(yǔ)句和 try catch 中的聲明的變量不管是否能夠執(zhí)行谎痢,都只會(huì)發(fā)生提前聲明,不會(huì)發(fā)生提前賦值卷雕。
解析:
// 如果一個(gè)變量聲明了但是未賦值节猿,那么輸出這個(gè)變量就會(huì)輸出 undefined

var num;
console.log(num);

// 如果一個(gè)變量沒有聲明也沒有賦值,那么就會(huì)報(bào)一個(gè)錯(cuò):

console.log(num);

// 輸出一個(gè)不存在的變量 Uncaught ReferenceError: num is not defined
// var 關(guān)鍵字進(jìn)行的變量提升

console.log(num);
var num = 123;
console.log(num);
var num = 456;
console.log(num);

// 變量提升之后的代碼:

var num;
console.log(num);
num = 123;
console.log(num);
num = 456;
console.log(num);
// function 關(guān)鍵字的變量提升
console.log(fn);
function fn() {
  console.log(1);
}

// 變量提升之后的代碼:

function fn() {
  console.log(1);
}
console.log(fn); // 輸出fn的函數(shù)體
// 3.1 return 之后的代碼依舊會(huì)發(fā)生變量提升  規(guī)則適用于1漫雕,2
function fn() {
  console.log(num);
  return;
  var num = 123;
}
fn();

// 變量提升之后的代碼:

function fn() {
  var num;
  console.log(num);
  return;
  num = 123;
}
fn(); // undefined
function fn() {
  console.log(fo);
  return;
  function fo() {}
}
fn();

// 變量提升之后的代碼:

function fn() {
  function fo() {}
  console.log(fo);
  return;
}
fn(); //輸出fo的函數(shù)體

//3.2 代碼報(bào)錯(cuò)之后的代碼依舊會(huì)進(jìn)行變量提升沐批,規(guī)則適用于1,2

console.log(num);
xsasfgdsfqdfsdf; //報(bào)一個(gè)錯(cuò)
var num = 123;
console.log(num);

// 變量提升之后的代碼:

var num;
console.log(num); //輸出 undefined
dsagdsqghdwfh; // 報(bào)一個(gè)錯(cuò)誤 ,錯(cuò)誤之后的代碼不會(huì)被執(zhí)行
num = 123;
console.log(num);//function 關(guān)鍵字
console.log(fn);
sasgfdhwhsdqg;
function fn() {}
console.log(fn);

// 變量提升之后的代碼:

function fn() {}
console.log(fn); // 輸出 fn 的函數(shù)體
asdgsdgdfgfdg; // 報(bào)一個(gè)錯(cuò)誤蝎亚,報(bào)錯(cuò)之后的代碼不會(huì)被執(zhí)行
console.log(fn);
//4 代碼不執(zhí)行,但是會(huì)進(jìn)行變量提升先馆,不過(guò)規(guī)則不適用于1,2
//4.1 if判斷語(yǔ)句
console.log(num);
if (false) {
    var num = 123;
}
console.log(num)

//  變量提升之后的代碼:
var num;
console.log(num); //undefined
if (false) {
    num = 123;
}
console.log(num) //undefined

console.log(fn);
if (false) {
    function fn() {}
}
console.log(fn);

// 變量提升之后的代碼:
var fn;
function fn;
console.log(fn) //undefined
if (false) {
    function fn() {}
}
console.log(fn) //undefined
if(false){
  function fn() {}
}
console.log(fn) //undefined
// try catch
try {
  console.log(num);
} catch (e) {
  var num = 123;
}
console.log(num);

var num;
try {
  console.log(num); // undefined
} catch (e) {
  num = 123;
}
console.log(num); // undefined

try {
  console.log(fn);
} catch (e) {
  function fn() {}
}
console.log(fn);

var fn;
try {
  console.log(fn); // undefined
} catch (e) {
  num = 123;
}
console.log(fn); // undefined
3.如何阻止冒泡與默認(rèn)行為

阻止冒泡行為:
非 IE 瀏覽器 stopPropagation()发框,IE 瀏覽器 window.event.cancelBubble = true
阻止默認(rèn)行為:
非 IE 瀏覽器 preventDefault(),IE 瀏覽器 window.event.returnValue = false
解析:
當(dāng)需要阻止冒泡行為時(shí)煤墙,可以使用

function stopBubble(e) {
//如果提供了事件對(duì)象梅惯,則這是一個(gè)非IE瀏覽器
if (e && e.stopPropagation)
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
//否則,我們需要使用IE的方式來(lái)取消事件冒泡
else window.event.cancelBubble = true;
}
當(dāng)需要阻止默認(rèn)行為時(shí)仿野,可以使用

//阻止瀏覽器的默認(rèn)行為
function stopDefault(e) {
//阻止默認(rèn)瀏覽器動(dòng)作(W3C)
if (e && e.preventDefault) e.preventDefault();
//IE中阻止函數(shù)器默認(rèn)動(dòng)作的方式
else window.event.returnValue = false;
return false;
}

4.js 中 this 閉包 作用域

this:指向調(diào)用上下文
閉包:定義一個(gè)函數(shù)就開辟了一個(gè)局部作用域铣减,整個(gè) js 執(zhí)行環(huán)境有一個(gè)全局作用域
作用域:一個(gè)函數(shù)可以訪問(wèn)其他函數(shù)中的變量(閉包是一個(gè)受保護(hù)的變量空間)

var f = (function fn() {
  var name = 1;
  return function () {
    name++;
    console.log(name)
  }
})()
5.javascript 的同源策略

一段腳本只能讀取來(lái)自于同一來(lái)源的窗口和文檔的屬性
解析:
同源策略:限制從一個(gè)源加載的文檔或腳本如何與來(lái)自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制脚作。(來(lái)自 MDN 官方的解釋)
簡(jiǎn)單來(lái)說(shuō)就是:一段腳本只能讀取來(lái)自于同一來(lái)源的窗口和文檔的屬性葫哗,這里的同一來(lái)源指的是主機(jī)名缔刹、協(xié)議和端口號(hào)的組合
具體解釋:
(1)源包括三個(gè)部分:協(xié)議、域名劣针、端口(http 協(xié)議的默認(rèn)端口是 80)校镐。如果有任何一個(gè)部分不同,則源不同捺典,那就是跨域了鸟廓。
(2)限制:這個(gè)源的文檔沒有權(quán)利去操作另一個(gè)源的文檔。這個(gè)限制體現(xiàn)在:(要記捉蠹骸)Cookie引谜、LocalStorage 和 IndexDB 無(wú)法獲取。無(wú)法獲取和操作 DOM擎浴。不能發(fā)送 Ajax 請(qǐng)求员咽。我們要注意,Ajax 只適合同源的通信退客。
同源策略帶來(lái)的麻煩:ajax 在不同域名下的請(qǐng)求無(wú)法實(shí)現(xiàn)骏融,需要進(jìn)行跨域操作

6.事件冒泡與事件捕獲

事件冒泡:由最具體的元素(目標(biāo)元素)向外傳播到最不具體的元素
事件捕獲:由最不確定的元素到目標(biāo)元素

7.復(fù)雜數(shù)據(jù)類型如何轉(zhuǎn)變?yōu)樽址?/h5>

首先,會(huì)調(diào)用 valueOf 方法萌狂,如果方法的返回值是一個(gè)基本數(shù)據(jù)類型档玻,就返回這個(gè)值
如果調(diào)用 valueOf 方法之后的返回值仍舊是一個(gè)復(fù)雜數(shù)據(jù)類型,就會(huì)調(diào)用該對(duì)象的 toString 方法
如果 toString 方法調(diào)用之后的返回值是一個(gè)基本數(shù)據(jù)類型茫藏,就返回這個(gè)值误趴,
如果 toString 方法調(diào)用之后的返回值是一個(gè)復(fù)雜數(shù)據(jù)類型,就報(bào)一個(gè)錯(cuò)誤务傲。

8.javascript 中 this 的指向問(wèn)題

全局環(huán)境凉当、普通函數(shù)(非嚴(yán)格模式)指向 window
普通函數(shù)(嚴(yán)格模式)指向 undefined
函數(shù)作為對(duì)象方法及原型鏈指向的就是上一級(jí)的對(duì)象
構(gòu)造函數(shù)指向構(gòu)造的對(duì)象
DOM 事件中指向觸發(fā)事件的元素
箭頭函數(shù)
解析:
1、全局環(huán)境
全局環(huán)境下售葡,this 始終指向全局對(duì)象(window)看杭,無(wú)論是否嚴(yán)格模式;

// 在瀏覽器中挟伙,全局對(duì)象為 window 對(duì)象:

console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37

2楼雹、函數(shù)上下文調(diào)用
普通函數(shù)
普通函數(shù)內(nèi)部的 this 分兩種情況,嚴(yán)格模式和非嚴(yán)格模式尖阔。
(1)非嚴(yán)格模式下贮缅,沒有被上一級(jí)的對(duì)象所調(diào)用,this 默認(rèn)指向全局對(duì)象 window。

function f1() {
  return this;
}
f1() === window; // true

(2)嚴(yán)格模式下介却,this 指向 undefined谴供。

function f2() {
  "use strict"; // 這里是嚴(yán)格模式
  return this;
}
f2() === undefined; // true

函數(shù)作為對(duì)象的方法
(1)函數(shù)有被上一級(jí)的對(duì)象所調(diào)用,那么 this 指向的就是上一級(jí)的對(duì)象齿坷。
(2)多層嵌套的對(duì)象桂肌,內(nèi)部方法的 this 指向離被調(diào)用函數(shù)最近的對(duì)象(window 也是對(duì)象数焊,其內(nèi)部對(duì)象調(diào)用方法的 this 指向內(nèi)部對(duì)象, 而非 window)轴或。
//方式1

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};
//當(dāng) o.f()被調(diào)用時(shí)昌跌,函數(shù)內(nèi)的this將綁定到o對(duì)象。
console.log(o.f()); // logs 37

//方式2

var o = { prop: 37 };
function independent() {
  return this.prop;
}
//函數(shù)f作為o的成員方法調(diào)用
o.f = independent;
console.log(o.f()); // logs 37

//方式3
//this 的綁定只受最靠近的成員引用的影響

o.b = { g: independent, prop: 42 };
console.log(o.b.g()); // 42

特殊例子

// 例子1

var o = {
  a: 10,
  b: {
    // a:12,
    fn: function() {
      console.log(this.a); //undefined
      console.log(this); //{fn: ?}
    }
  }
};
o.b.fn();

// 例子2

var o = {
  a: 10,
  b: {
    a: 12,
    fn: function() {
      console.log(this.a); //undefined
      console.log(this); //window
    }
  }
};
var j = o.b.fn;
j();

// this永遠(yuǎn)指向的是最后調(diào)用它的對(duì)象照雁,也就是看它執(zhí)行的時(shí)候是誰(shuí)調(diào)用的蚕愤,例子2中雖然函數(shù)fn是被對(duì)象b所引用,但是在將fn賦值給變量j的時(shí)候并沒有執(zhí)行所以最終指向的是window饺蚊,這和例子1是不一樣的萍诱,例子1是直接執(zhí)行了fn
原型鏈中的 this
(1)如果該方法存在于一個(gè)對(duì)象的原型鏈上,那么 this 指向的是調(diào)用這個(gè)方法的對(duì)象污呼,就像該方法在對(duì)象上一樣裕坊。

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

上述例子中,對(duì)象 p 沒有屬于它自己的 f 屬性燕酷,它的 f 屬性繼承自它的原型籍凝。當(dāng)執(zhí)行 p.f()時(shí),會(huì)查找 p 的原型鏈苗缩,找到 f 函數(shù)并執(zhí)行饵蒂。因?yàn)?f 是作為 p 的方法調(diào)用的,所以函數(shù)中的 this 指向 p酱讶。
(2)相同的概念也適用于當(dāng)函數(shù)在一個(gè) getter 或者 setter 中被調(diào)用退盯。用作 getter 或 setter 的函數(shù)都會(huì)把 this 綁定到設(shè)置或獲取屬性的對(duì)象。
(3)call()和 apply()方法:當(dāng)函數(shù)通過(guò) Function 對(duì)象的原型中繼承的方法 call() 和 apply() 方法調(diào)用時(shí)泻肯, 其函數(shù)內(nèi)部的 this 值可綁定到 call() & apply() 方法指定的第一個(gè)對(duì)象上渊迁, 如果第一個(gè)參數(shù)不是對(duì)象,JavaScript 內(nèi)部會(huì)嘗試將其轉(zhuǎn)換成對(duì)象然后指向它灶挟。

function add(c, d) {
  return this.a + this.b + c + d;
}
var o = { a: 1, b: 3 };

add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

function tt() {
  console.log(this);
}

// 第一個(gè)參數(shù)不是對(duì)象琉朽,JavaScript內(nèi)部會(huì)嘗試將其轉(zhuǎn)換成對(duì)象然后指向它。
tt.call(5); // 內(nèi)部轉(zhuǎn)成 Number {[[PrimitiveValue]]: 5}
tt.call("asd");
// 內(nèi)部轉(zhuǎn)成 String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}
(4)bind()方法:由 ES5 引入稚铣, 在 Function 的原型鏈上箱叁, Function.prototype.bind
通過(guò) bind 方法綁定后, 函數(shù)將被永遠(yuǎn)綁定在其第一個(gè)參數(shù)對(duì)象上榛泛, 而無(wú)論其在什么情況下被調(diào)用。

function f() {
  return this.a;
}

var g = f.bind({ a: "azerty" });
console.log(g()); // azerty

var o = { a: 37, f: f, g: g };
console.log(o.f(), o.g()); // 37, azerty2.4 

構(gòu)造函數(shù)中的 this當(dāng)一個(gè)函數(shù)用作構(gòu)造函數(shù)時(shí)(使用 new 關(guān)鍵字)噩斟,它的 this 被綁定到正在構(gòu)造的新對(duì)象曹锨。構(gòu)造器返回的默認(rèn)值是 this 所指的那個(gè)對(duì)象,也可以手動(dòng)返回其他的對(duì)象剃允。

function C() {
  this.a = 37;
}

var o = new C();
console.log(o.a); // 37

// 為什么this會(huì)指向o沛简?
//首先new關(guān)鍵字會(huì)創(chuàng)建一個(gè)空的對(duì)象齐鲤,然后會(huì)自動(dòng)調(diào)用一個(gè)函數(shù)apply方法,將this指向這個(gè)空對(duì)象椒楣,這樣的話函數(shù)內(nèi)部的this就會(huì)被這個(gè)空的對(duì)象替代给郊。

function C2() {
  this.a = 37;
  return { a: 38 }; // 手動(dòng)設(shè)置返回{a:38}對(duì)象
}

o = new C2();
console.log(o.a); // 38

特殊例子
當(dāng) this 碰到 return 時(shí)

// 例子1

function fn() {
  this.user = "追夢(mèng)子";
  return {};
}
var a = new fn();
console.log(a.user); //undefined

// 例子2

function fn() {
  this.user = "追夢(mèng)子";
  return function() {};
}
var a = new fn();
console.log(a.user); //undefined

// 例子3

function fn() {
  this.user = "追夢(mèng)子";
  return 1;
}
var a = new fn();
console.log(a.user); //追夢(mèng)子

// 例子4

function fn() {
  this.user = "追夢(mèng)子";
  return undefined;
}
var a = new fn();
console.log(a.user); //追夢(mèng)子

// 例子5

function fn() {
  this.user = "追夢(mèng)子";
  return undefined;
}
var a = new fn();
console.log(a); //fn {user: "追夢(mèng)子"}

// 例子6
// 雖然null也是對(duì)象,但是在這里this還是指向那個(gè)函數(shù)的實(shí)例捧灰,因?yàn)閚ull比較特殊

function fn() {
  this.user = "追夢(mèng)子";
  return null;
}
var a = new fn();
console.log(a.user); //追夢(mèng)子

// 總結(jié):如果返回值是一個(gè)對(duì)象淆九,那么this指向的就是那個(gè)返回的對(duì)象,如果返回值不是一個(gè)對(duì)象那么this還是指向函數(shù)的實(shí)例毛俏。
setTimeout & setInterval
(1)對(duì)于延時(shí)函數(shù)內(nèi)部的回調(diào)函數(shù)的 this 指向全局對(duì)象 window炭庙;
(2)可以通過(guò) bind()方法改變內(nèi)部函數(shù) this 指向。
//默認(rèn)情況下代碼

function Person() {
  this.age = 0;
  setTimeout(function() {
    console.log(this);
  }, 3000);
}

var p = new Person(); //3秒后返回 window 對(duì)象
//通過(guò)bind綁定

function Person() {
  this.age = 0;
  setTimeout(
    function() {
      console.log(this);
    }.bind(this),
    3000
  );
}

var p = new Person(); //3秒后返回構(gòu)造函數(shù)新生成的對(duì)象 Person{...}
3煌寇、在 DOM 事件中
作為一個(gè) DOM 事件處理函數(shù)
當(dāng)函數(shù)被用作事件處理函數(shù)時(shí)焕蹄,它的 this 指向觸發(fā)事件的元素(針對(duì) addEventListener 事件)。
// 被調(diào)用時(shí)阀溶,將關(guān)聯(lián)的元素變成藍(lán)色
function bluify(e) {
//this指向所點(diǎn)擊元素
console.log("this === e.currentTarget", this === e.currentTarget); // 總是 true
// 當(dāng) currentTarget 和 target 是同一個(gè)對(duì)象時(shí)為 true
console.log("this === e.target", this === e.target);
this.style.backgroundColor = "#A5D9F3";
}

// 獲取文檔中的所有元素的列表
var elements = document.getElementsByTagName("*");

// 將bluify作為元素的點(diǎn)擊監(jiān)聽函數(shù)腻脏,當(dāng)元素被點(diǎn)擊時(shí),就會(huì)變成藍(lán)色
for (var i = 0; i ? elements.length; i++) {
elements[i].addEventListener("click", bluify, false);
}
作為一個(gè)內(nèi)聯(lián)事件處理函數(shù)
(1)當(dāng)代碼被內(nèi)聯(lián)處理函數(shù)調(diào)用時(shí)银锻,它的 this 指向監(jiān)聽器所在的 DOM 元素永品;
(2)當(dāng)代碼被包括在函數(shù)內(nèi)部執(zhí)行時(shí),其 this 指向等同于 普通函數(shù)直接調(diào)用的情況徒仓,即在非嚴(yán)格模式指向全局對(duì)象 window腐碱,在嚴(yán)格模式指向 undefined:
?button onclick="console.log(this)"?show me?/button?
?button onclick="(function () {console.log(this)})()"?show inner this?/button?
?button onclick="(function () {'use strict'; console.log(this)})()"?
use strict
?/button?
// 控制臺(tái)打印
?button onclick="console.log(this)"?show me?/button?
Window {postMessage: ?, blur: ?, focus: ?, close: ?, parent: Window, …}
undefined
4、箭頭函數(shù)
全局環(huán)境中
在全局代碼中掉弛,箭頭函數(shù)被設(shè)置為全局對(duì)象:

var globalObject = this;
var foo = () =? this;
console.log(foo() === globalObject); // true

this 捕獲上下文
箭頭函數(shù)沒有自己的 this症见,而是使用箭頭函數(shù)所在的作用域的 this,即指向箭頭函數(shù)定義時(shí)(而不是運(yùn)行時(shí))所在的作用域殃饿。
//1谋作、箭頭函數(shù)在函數(shù)內(nèi)部,以非方法的方法使用

function Person() {
  this.age = 0;
  setInterval(() =? {
    this.age++;
  }, 3000);
}
var p = new Person(); //Person{age: 0}

//普通函數(shù)作為內(nèi)部函數(shù)

function Person() {
  this.age = 0;
  setInterval(function() {
    console.log(this);
    this.age++;
  }, 3000);
}
var p = new Person(); //Window{...}

在 setTimeout 中的 this 指向了構(gòu)造函數(shù)新生成的對(duì)象乎芳,而普通函數(shù)指向了全局 window 對(duì)象遵蚜。

箭頭函數(shù)作為對(duì)象的方法
使用箭頭函數(shù)作為對(duì)象的方法使用,指向全局 window 對(duì)象奈惑;而普通函數(shù)作為對(duì)象的方法使用吭净,則指向調(diào)用的對(duì)象。

var obj = {
  i: 10,
  b: () =? console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
};
obj.b(); // undefined window{...}
obj.c(); // 10 Object {...}

箭頭函數(shù)中肴甸,call()寂殉、apply()、bind()方法無(wú)效
var adder = {
base: 1,
//對(duì)象的方法內(nèi)部定義箭頭函數(shù)原在,this是箭頭函數(shù)所在的作用域的this友扰,
//而方法add的this指向adder對(duì)象彤叉,所以箭頭函數(shù)的this也指向adder對(duì)象。

  add: function(a) {
    var f = v =? v + this.base;
    return f(a);
  },

//普通函數(shù)f1的this指向window

  add1: function() {
    var f1 = function() {
      console.log(this);
    };
    return f1();
  },
  addThruCall: function inFun(a) {
    var f = v =? v + this.base;
    var b = {
      base: 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1)); // 輸出 2

adder.add1(); //輸出全局對(duì)象 window{...}
console.log(adder.addThruCall(1)); // 仍然輸出 2(而不是3村怪,其內(nèi)部的this并沒有因?yàn)閏all() 而改變秽浇,其this值仍然為函數(shù)inFun的this值,指向?qū)ο骯dder
this 指向固定化
箭頭函數(shù)可以讓 this 指向固定化甚负,這種特性很有利于封裝回調(diào)函數(shù)

var handler = {
  id: "123456",

  init: function() {
    document.addEventListener(
      "click",
      event =? this.doSomething(event.type),
      false
    );
  },

  doSomething: function(type) {
    console.log("Handling " + type + " for " + this.id);
  }
};

上面代碼的 init 方法中柬焕,使用了箭頭函數(shù),這導(dǎo)致這個(gè)箭頭函數(shù)里面的 this腊敲,總是指向 handler 對(duì)象击喂。如果不使用箭頭函數(shù)則指向全局 document 對(duì)象。

箭頭函是不適用場(chǎng)景
(1)箭頭函數(shù)不適合定義對(duì)象的方法(方法內(nèi)有 this)碰辅,因?yàn)榇藭r(shí)指向 window懂昂;
(2)需要?jiǎng)討B(tài) this 的時(shí)候,也不應(yīng)使用箭頭函數(shù)没宾。
//例1凌彬,this指向定義箭頭函數(shù)所在的作用域,它位于對(duì)象cat內(nèi)循衰,但cat不能構(gòu)成一個(gè)作用域铲敛,所以指向全局window,改成普通函數(shù)后this指向cat對(duì)象会钝。

const cat = {
  lives: 9,
  jumps: () =? {
    this.lives--;
  }
};

//例2伐蒋,此時(shí)this也是指向window,不能動(dòng)態(tài)監(jiān)聽button迁酸,改成普通函數(shù)后this指向按鈕對(duì)象先鱼。

var button = document.getElementById("press");
button.addEventListener("click", () =? {
  this.classList.toggle("on");
});
9.ES6 都有什么 Iterator 遍歷器

Set、Map
解析:

遍歷器(Iterator)是一種接口奸鬓,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問(wèn)機(jī)制焙畔。任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)
Iterator 的作用有三個(gè):
一是為各種數(shù)據(jù)結(jié)構(gòu)串远,提供一個(gè)統(tǒng)一的宏多、簡(jiǎn)便的訪問(wèn)接口;
二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列澡罚;
三是 ES6 創(chuàng)造了一種新的遍歷命令 for...of 循環(huán)伸但,Iterator 接口主要供 for...of 消費(fèi)。
默認(rèn)部署了 Iterator 的數(shù)據(jù)有 Array留搔、Map更胖、Set、String、TypedArray函喉、arguments、NodeList 對(duì)象荣月,ES6 中有的是 Set管呵、Map**、

10. ES6 中類的定義

// 1哺窄、類的基本定義

class Parent {
  constructor(name = "小白") {
    this.name = name;
  }
}

// 2捐下、生成一個(gè)實(shí)例

let g_parent = new Parent();
console.log(g_parent); //{name: "小白"}
let v_parent = new Parent("v"); // 'v'就是構(gòu)造函數(shù)name屬性 , 覆蓋構(gòu)造函數(shù)的name

屬性值

console.log(v_parent); // {name: "v"}

// 3、繼承

class Parent {
  //定義一個(gè)類
  constructor(name = "小白") {
    this.name = name;
  }
}

class Child extends Parent {}

console.log("繼承", new Child()); // 繼承 {name: "小白"}

// 4萌业、繼承傳遞參數(shù)

class Parent {
  //定義一個(gè)類
  constructor(name = "小白") {
    this.name = name;
  }
}

class Child extends Parent {
  constructor(name = "child") {
    // 子類重寫name屬性值
    super(name); // 子類向父類修改 super一定放第一行
    this.type = "preson";
  }
}
console.log("繼承", new Child("hello")); // 帶參數(shù)覆蓋默認(rèn)值  繼承{name: "hello", type: "preson"}

// 5坷襟、ES6重新定義的ES5中的訪問(wèn)器屬性

class Parent {
  //定義一個(gè)類
  constructor(name = "小白") {
    this.name = name;
  }

  get longName() {
    // 屬性
    return "mk" + this.name;
  }

  set longName(value) {
    this.name = value;
  }
}

let v = new Parent();
console.log("getter", v.longName); // getter mk小白

v.longName = "hello";
console.log("setter", v.longName); // setter mkhello// 

6、類的靜態(tài)方法

class Parent {
  //定義一個(gè)類
  constructor(name = "小白") {
    this.name = name;
  }

  static tell() {
    // 靜態(tài)方法:通過(guò)類去調(diào)用生年,而不是實(shí)例
    console.log("tell");
  }
}

Parent.tell(); // tell// 

7婴程、類的靜態(tài)屬性:

class Parent {
  //定義一個(gè)類
  constructor(name = "小白") {
    this.name = name;
  }

  static tell() {
    // 靜態(tài)方法:通過(guò)類去調(diào)用,而不是實(shí)例
    console.log("tell"); // tell
  }
}

Parent.type = "test"; // 定義靜態(tài)屬性

console.log("靜態(tài)屬性", Parent.type); // 靜態(tài)屬性 test

let v_parent = new Parent();
console.log(v_parent); // {name: "小白"}  沒有tell方法和type屬性
11.說(shuō)說(shuō)你對(duì) promise 的了解

Promise 是異步編程的一種解決方案抱婉,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件監(jiān)聽——更合理和更強(qiáng)大档叔。
所謂 Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器蒸绩,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果衙四。從語(yǔ)法上說(shuō),Promise 是一個(gè)對(duì)象患亿,從它可以獲取異步操作的消息传蹈。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理步藕。Promise 對(duì)象有以下兩個(gè)特點(diǎn):

對(duì)象的狀態(tài)不受外界影響惦界,Promise 對(duì)象代表一個(gè)異步操作,有三種狀態(tài):Pending(進(jìn)行中)漱抓、Resolved(已完成表锻,又稱 Fulfilled)和 Rejected(已失敗)
一旦狀態(tài)改變乞娄,就不會(huì)再變瞬逊,任何時(shí)候都可以得到這個(gè)結(jié)果。

12.Set 數(shù)據(jù)結(jié)構(gòu)

es6 方法,
Set 本身是一個(gè)構(gòu)造函數(shù)仪或,它類似于數(shù)組确镊,但是成員值都是唯一的。

const set = new Set([1, 2, 3, 4, 4]);
console.log([...set]); // [1,2,3,4]
console.log(Array.from(new Set([2, 3, 3, 5, 6]))); //[2,3,5,6]
13.箭頭函數(shù)需要注意的地方

箭頭函數(shù)有幾個(gè)使用注意點(diǎn)范删。

(1)函數(shù)體內(nèi)的 this 對(duì)象蕾域,就是定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象。
(2)不可以當(dāng)作構(gòu)造函數(shù)旨巷,也就是說(shuō)巨缘,不可以使用 new 命令,否則會(huì)拋出一個(gè)錯(cuò)誤采呐。
(3)不可以使用 arguments 對(duì)象若锁,該對(duì)象在函數(shù)體內(nèi)不存在。如果要用斧吐,可以用 rest 參數(shù)代替又固。
(4)不可以使用 yield 命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)煤率。
上面四點(diǎn)中仰冠,第一點(diǎn)尤其值得注意。this 對(duì)象的指向是可變的蝶糯,但是在箭頭函數(shù)中洋只,它是固定的。

function foo() {
setTimeout(() =? {
  console.log("id:", this.id);
}, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42
14.ES6 如何動(dòng)態(tài)加載 import
import("lodash").then(_ =? {
  // Do something with lodash (a.k.a '_')...
});
15.ECMAScript6 怎么寫class么昼捍,為什么會(huì)出現(xiàn)class這種東西?
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
     return '('+this.x+', '+this.y+')';
  }
}
16.對(duì)象淺拷貝和深拷貝有什么區(qū)別

在 JS 中木张,除了基本數(shù)據(jù)類型,還存在對(duì)象端三、數(shù)組這種引用類型舷礼。
基本數(shù)據(jù)類型,拷貝是直接拷貝變量的值郊闯,而引用類型拷貝的其實(shí)是變量的地址妻献。

let o1 = {a: 1}
let o2 = o1

在這種情況下,如果改變 o1 或 o2 其中一個(gè)值的話团赁,另一個(gè)也會(huì)變育拨,因?yàn)樗鼈兌贾赶蛲粋€(gè)地址。

o2.a = 3
console.log(o1.a) // 3

而淺拷貝和深拷貝就是在這個(gè)基礎(chǔ)之上做的區(qū)分欢摄,如果在拷貝這個(gè)對(duì)象的時(shí)候绍载,只對(duì)基本數(shù)據(jù)類型進(jìn)行了拷貝扶歪,而對(duì)引用數(shù)據(jù)類型只是進(jìn)行了引用的傳遞震檩,而沒有重新創(chuàng)建一個(gè)新的對(duì)象撩匕,則認(rèn)為是淺拷貝。反之绿淋,在對(duì)引用數(shù)據(jù)類型進(jìn)行拷貝的時(shí)候闷畸,創(chuàng)建了一個(gè)新的對(duì)象,并且復(fù)制其內(nèi)的成員變量吞滞,則認(rèn)為是深拷貝佑菩。

17.JS 怎么實(shí)現(xiàn)一個(gè)類盾沫。怎么實(shí)例化這個(gè)類

嚴(yán)格來(lái)講 js 中并沒有類的概念,不過(guò) js 中的函數(shù)可以作為構(gòu)造函數(shù)來(lái)使用殿漠,通過(guò) new 來(lái)實(shí)例化赴精,其實(shí)函數(shù)本身也是一個(gè)對(duì)象。

18.如何編寫高性能的 Javascript绞幌?

使用 DocumentFragment 優(yōu)化多次 append
通過(guò)模板元素 clone 祖娘,替代 createElement
使用一次 innerHTML 賦值代替構(gòu)建 dom 元素
使用 firstChild 和 nextSibling 代替 childNodes 遍歷 dom 元素
使用 Array 做為 StringBuffer ,代替字符串拼接的操作
將循環(huán)控制量保存到局部變量
順序無(wú)關(guān)的遍歷時(shí)啊奄,用 while 替代 for
將條件分支,按可能性順序從高到低排列
在同一條件子的多( ?2 )條件分支時(shí)掀潮,使用 switch 優(yōu)于 if
使用三目運(yùn)算符替代條件分支
需要不斷執(zhí)行的時(shí)候菇夸,優(yōu)先考慮使用 setInterval

19.數(shù)組和對(duì)象有哪些原生方法,列舉一下仪吧?
Array.concat( ) 連接數(shù)組
Array.join( ) 將數(shù)組元素連接起來(lái)以構(gòu)建一個(gè)字符串
Array.length 數(shù)組的大小
Array.pop( ) 刪除并返回?cái)?shù)組的最后一個(gè)元素
Array.push( ) 給數(shù)組添加元素
Array.reverse( ) 顛倒數(shù)組中元素的順序
Array.shift( ) 將元素移出數(shù)組
Array.slice( ) 返回?cái)?shù)組的一部分
Array.sort( ) 對(duì)數(shù)組元素進(jìn)行排序
Array.splice( ) 插入庄新、刪除或替換數(shù)組的元素
Array.toLocaleString( ) 把數(shù)組轉(zhuǎn)換成局部字符串
Array.toString( ) 將數(shù)組轉(zhuǎn)換成一個(gè)字符串
Array.unshift( ) 在數(shù)組頭部插入一個(gè)元素
Object.hasOwnProperty( ) 檢查屬性是否被繼承
Object.isPrototypeOf( ) 一個(gè)對(duì)象是否是另一個(gè)對(duì)象的原型
Object.propertyIsEnumerable( ) 是否可以通過(guò) for/in 循環(huán)看到屬性
Object.toLocaleString( ) 返回對(duì)象的本地字符串表示
Object.toString( ) 定義一個(gè)對(duì)象的字符串表示
Object.valueOf( ) 指定對(duì)象的原始值
20.documen.write 和 innerHTML 的區(qū)別?

document.write 是重寫整個(gè) document, 寫入內(nèi)容是字符串的 html
innerHTML 是 HTMLElement 的屬性,是一個(gè)元素的內(nèi)部 html 內(nèi)容

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末薯鼠,一起剝皮案震驚了整個(gè)濱河市择诈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌出皇,老刑警劉巖羞芍,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異郊艘,居然都是意外死亡荷科,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門纱注,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)畏浆,“玉大人,你說(shuō)我怎么就攤上這事狞贱】袒瘢” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵瞎嬉,是天一觀的道長(zhǎng)蝎毡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)氧枣,這世上最難降的妖魔是什么顶掉? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮挑胸,結(jié)果婚禮上痒筒,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好簿透,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布移袍。 她就那樣靜靜地躺著,像睡著了一般老充。 火紅的嫁衣襯著肌膚如雪葡盗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天啡浊,我揣著相機(jī)與錄音觅够,去河邊找鬼。 笑死巷嚣,一個(gè)胖子當(dāng)著我的面吹牛喘先,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播廷粒,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窘拯,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了坝茎?” 一聲冷哼從身側(cè)響起涤姊,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗤放,沒想到半個(gè)月后思喊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡次酌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年搔涝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片和措。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庄呈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出派阱,到底是詐尸還是另有隱情诬留,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布贫母,位于F島的核電站文兑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏腺劣。R本人自食惡果不足惜绿贞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望橘原。 院中可真熱鬧籍铁,春花似錦涡上、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至增显,卻和暖如春雁佳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背同云。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工糖权, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炸站。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓星澳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親武契。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,233評(píng)論 0 4
  • 1. this之謎 在JavaScript中荡含,this是當(dāng)前執(zhí)行函數(shù)的上下文咒唆。因?yàn)镴avaScript有4種不同的...
    百里少龍閱讀 999評(píng)論 0 3
  • 1.自執(zhí)行函數(shù)?用于什么場(chǎng)景?好處? 自執(zhí)行函數(shù):1释液、聲明一個(gè)匿名函數(shù)2全释、馬上調(diào)用這個(gè)匿名函數(shù)。作用:創(chuàng)建一個(gè)獨(dú)立...
    一只小丫丫閱讀 174評(píng)論 0 0
  • 第一章 錯(cuò)誤處理: 錯(cuò)誤: 程序運(yùn)行過(guò)程中误债,導(dǎo)致程序無(wú)法正常執(zhí)行的現(xiàn)象(即bug) 現(xiàn)象: 程序一旦出錯(cuò)浸船,默認(rèn)會(huì)報(bào)...
    fastwe閱讀 1,116評(píng)論 0 1
  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語(yǔ)言來(lái)說(shuō)都是核心的概念寝蹈。通過(guò)函數(shù)可以封裝任意多條語(yǔ)句李命,而且...
    道無(wú)虛閱讀 4,563評(píng)論 0 5