2018-06-27

JavaScript(面向?qū)ο?原型理解+繼承+作用域鏈和閉包+this使用總結(jié))

一俄认、面向?qū)ο?/h1>

1个少、什么是面向?qū)ο?/p>

? 面向?qū)ο缶褪前褬?gòu)成問題事物分解成多個(gè)對(duì)象,建立對(duì)象不是為了完成某個(gè)步驟眯杏,而是描述某個(gè)事物在這個(gè)解決問題的步驟中的行為夜焦。

1.面向?qū)ο笫且环N思維方法

2.面向?qū)ο笫且环N編程方法

3.面向?qū)ο蟛⒉恢会槍?duì)某一種編程語言

2、面向?qū)ο蠛兔嫦蜻^程的區(qū)別和聯(lián)系

1.面向過程過程側(cè)重整個(gè)問題的解決步驟岂贩,著眼局部或者具體

2.面向?qū)ο髠?cè)重具體的功能茫经,讓某個(gè)對(duì)象具有這樣的功能。更加側(cè)重于整體萎津。

各自的優(yōu)缺點(diǎn):
?
面向過程的優(yōu)點(diǎn):
流程化使得編程任務(wù)明確卸伞,在開發(fā)之前基本考慮實(shí)現(xiàn)的方法和最終結(jié)果;
效率高锉屈,面向過程強(qiáng)調(diào)代碼的短小精悍荤傲,善于結(jié)合數(shù)據(jù)結(jié)構(gòu)來開發(fā)高效率程序;
流程明確颈渊,具體步驟清楚遂黍,便于節(jié)點(diǎn)分析终佛。

  面向過程的缺點(diǎn):
      需要深入的思考,耗費(fèi)精力妓湘,代碼重用性低查蓉,擴(kuò)展能力差,維護(hù)起來難度比較高榜贴,
      對(duì)復(fù)雜業(yè)務(wù)來說,面向過程的模塊難度較高妹田,耦合度也比較高唬党。

?
面向?qū)ο蟮膬?yōu)點(diǎn):
結(jié)構(gòu)清晰,程序便于模塊化鬼佣,結(jié)構(gòu)化驶拱,抽象化,更加符合人類的思維方式晶衷;
封裝性蓝纲,將事務(wù)高度抽象,從而便于流程中的行為分析晌纫,也便于操作和自仕懊浴;
容易擴(kuò)展锹漱,代碼重用率高箭养,可繼承,可覆蓋哥牍;
實(shí)現(xiàn)簡單毕泌,可有效地減少程序的維護(hù)工作量,軟件開發(fā)效率高嗅辣。
?
面向?qū)ο蟮娜秉c(diǎn)是:
效率低撼泛,面向?qū)ο笤诿嫦蜻^程的基礎(chǔ)上高度抽象,從而和代碼底層的直接交互非常少機(jī)會(huì)澡谭,從而不適合底層開發(fā)和游戲甚至多媒體開發(fā)愿题;
復(fù)雜性,對(duì)于事務(wù)開發(fā)而言译暂,事務(wù)本身是面向過程的抠忘,過度的封裝導(dǎo)致事務(wù)本身的復(fù)雜性提高。

3外永、面向?qū)ο蟮膶?shí)現(xiàn)方式

? 面向?qū)ο蟮膶?shí)現(xiàn)主流有兩種方式:基于類的面向?qū)ο蠛突谠偷拿嫦驅(qū)ο蟆?/p>

? 面向?qū)ο笕筇卣鳎?/p>

● 封裝

也就是把客觀事物封裝成抽象的類或具體的對(duì)象崎脉,并且類或?qū)ο罂梢园炎约旱臄?shù)據(jù)和方法只讓可信的類或者對(duì)象操作,對(duì)不可信的進(jìn)行信息隱藏伯顶。

● 繼承

可以讓某個(gè)類型的對(duì)象獲得另一個(gè)類型的對(duì)象的屬性的方法

● 多肽

不同實(shí)例的相同方法在不同情形有不同表現(xiàn)形式囚灼。多態(tài)機(jī)制使具有不同內(nèi)部結(jié)構(gòu)的對(duì)象可以共享相同的外部接口骆膝。

3.1 基于類的面向?qū)ο?/h1>

? 典型的語言:Java、C#

對(duì)象(object)依靠 類(class)來產(chǎn)生

3.2 基于原型的面向?qū)ο?/h1>

? 典型的語言:JavaScript

對(duì)象(object)則是依靠 構(gòu)造器(constructor)利用 原型(prototype)構(gòu)造出來的

4灶体、多種創(chuàng)建對(duì)象的方式

4.1 使用new Object()創(chuàng)建

4.2 工廠模式創(chuàng)建

? 工廠模式是軟件工程領(lǐng)域一種廣為人知的設(shè)計(jì)模式阅签,這種模式抽象了創(chuàng)建具體對(duì)象的過程,考慮到在 ECMAScript 中無法創(chuàng)建類蝎抽,開發(fā)人員就發(fā)明了一種函數(shù)政钟,用函數(shù)來封裝以特定接口創(chuàng)建對(duì)象的細(xì)節(jié)。

4.3 構(gòu)造函數(shù)模式創(chuàng)建

? 為了解決對(duì)象類型識(shí)別問題樟结,又提出了構(gòu)造函數(shù)模式养交。這種模式,其實(shí)在我們創(chuàng)建一些原生對(duì)象的時(shí)候瓢宦,比如Array碎连、Object都是調(diào)用的他們的構(gòu)造函數(shù)。
<script type="text/javascript">
function Person (name, age, sex) {
this.name = name;

      this.age = age;
      this.sex = sex;
      
      this.eat = function () {
          alert(this.name + " Eat food");
      }
  }
  var p1 = new Person("Jack", 20, "man");
  p1.eat();   //Jack Eat food
  var p1 = new Person("Mark", 30, "man");
  p1.eat();   //Mark Eat food
  alert(p1 instanceof Person);    

</script>

5驮履、構(gòu)造函數(shù)與普通函數(shù)的關(guān)系

1.

他們都是函數(shù)鱼辙。構(gòu)造函數(shù)也是函數(shù),也可以像普通的函數(shù)一樣進(jìn)行調(diào)用玫镐。 做普通函數(shù)調(diào)用的時(shí)候倒戏,因?yàn)闆]有創(chuàng)建新的對(duì)象,所以this其實(shí)指向了window對(duì)象摘悴。

function Person(){
this.name = "Jack"; // 把name屬性添加到了window對(duì)象上面
alert(this === window); //如果不作為構(gòu)造方法調(diào)用峭梳,則 是true
}
Person(); // 把構(gòu)造函數(shù)當(dāng)做普通方法調(diào)用。這個(gè)時(shí)候內(nèi)部的this指向了weindow
alert(window.name); //Jack
function Human(){
this.name = "Mark";
alert(this instanceof window); // false
alert(this instanceof Human); //true
}
var h = new Human(); //當(dāng)做構(gòu)造函數(shù)來調(diào)用蹂喻,創(chuàng)建一個(gè)對(duì)象
alert(h.name);

2.

構(gòu)造函數(shù)和普通函數(shù)僅僅也僅僅是調(diào)用方式的不同葱椭。也就是說,隨便一個(gè)函數(shù)你如果用new 的方式去使用口四,那么他就是一個(gè)構(gòu)造函數(shù)孵运。

3.

為了區(qū)別,如果一個(gè)函數(shù)想作為構(gòu)造函數(shù)蔓彩,作為國際慣例治笨,最好把這個(gè)構(gòu)造函數(shù)的首字母大寫。

4赤嚼、閉包

<script type="text/javascript">
function createSumFunction(num1, num2){
return function () {
return num1 + num2;
};
}
var sumFun = createSumFunction(3, 4);
var sum = sumFun();
alert(sum);//7
</script>

在上面的代碼中旷赖,createSumFunction函數(shù)返回了一個(gè)匿名函數(shù),而這個(gè)匿名函數(shù)使用了createSumFunction函數(shù)中的局部變量(參數(shù))更卒,即使createSumFunction這個(gè)函數(shù)執(zhí)行結(jié)束了等孵,由于作用域鏈的存在,他的局部變量在匿名函數(shù)中仍然可以使用蹂空,這個(gè)匿名函數(shù)就是閉包俯萌。

? 閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)果录。

? 閉包是一種特殊的對(duì)象。它由兩部分構(gòu)成: 函數(shù)咐熙,以及創(chuàng)建該函數(shù)的環(huán)境 弱恒。環(huán)境由閉包創(chuàng)建時(shí)在作用域中的任何局部變量組成。在我們的例子中棋恼,sumFun 是一個(gè)閉包返弹,由 匿名 函數(shù)和閉包創(chuàng)建時(shí)存在的num1和num2 兩個(gè)局部變量組成。

5蘸泻、閉包的應(yīng)用

5.1 返回外部函數(shù)的局部變量

<script type="text/javascript">
function outer () {
var num = 5;
//定義一個(gè)內(nèi)部函數(shù)
function inner () {
//內(nèi)部函數(shù)的返回值是外部函數(shù)的一個(gè)局部變量
return num;
}
//把局部變量的值++
num++;
// 返回內(nèi)部函數(shù)
return inner;
}
var num = outer()(); // 6
alert(num);
</script>

說明:

1.

這例子中琉苇,雖然函數(shù)的聲明在num++之前,但是函數(shù)返回的時(shí)候num已經(jīng)++過了悦施,所以只是num自增之后的值。

2.

結(jié)論:閉包中使用的局部變量的值去团,一定是局部變量的最后的值抡诞。

5.2 使用函數(shù)自執(zhí)行和閉包封裝對(duì)象

封裝一個(gè)能夠增刪改查的對(duì)象

<script type="text/javascript">
var person = (function () {
//聲明一個(gè)對(duì)象,增刪改查均是針對(duì)這個(gè)對(duì)象
var personInfo = {
name : "李四",
age : 20
};
//返回一個(gè)對(duì)象土陪,這個(gè)對(duì)象中封裝了一些對(duì)personInfor操作的方法
return {
//根據(jù)給定的屬性獲取這個(gè)屬性的值
getInfo : function (property) {
return personInfo[property];
},
//修改一個(gè)屬性值
modifyInfo : function (property, newValue) {
personInfo[property] = newValue;

          },
          //添加新的屬性
          addInfo : function (property, value) {
              personInfo[property] = value;
              
          },
           //刪除指定的屬性
          delInfo : function (property) {
              delete personInfo[property];
              
          }
      }
  })();
  alert(person.getInfo("name"));
  person.addInfo("sex", "男");
  alert(person.getInfo("sex"));

</script>

五昼汗、this使用總結(jié)

1、this使用總結(jié)

<script>
/*
* 默認(rèn)綁定:
* 當(dāng)直接調(diào)用一個(gè)函數(shù)的時(shí)候鬼雀,就是默認(rèn)綁定
* 1顷窒、非嚴(yán)格模式下,默認(rèn)綁定到window上
*
* 隱式綁定:
* 當(dāng)使用 對(duì)象.方法() 這種方式調(diào)用源哩,稱之為隱式綁定
* this綁定到前面的那個(gè)對(duì)象上
*
* new 綁定:
* 使用new來調(diào)用構(gòu)造函數(shù)的方式
* this是綁定在新創(chuàng)建的那個(gè)對(duì)象上
*
* 顯示綁定:
* call鞋吉,apply:
* 都是一錘子買賣,僅僅這一次調(diào)用的時(shí)候使用了顯示綁定励烦,對(duì)原函數(shù)沒有如何的影響
*
* call和apply的區(qū)別:就是參數(shù)的傳遞方式
* call:一個(gè)一個(gè)的傳遞
* apply:把要傳遞的參數(shù)封裝到一個(gè)數(shù)組中去傳遞
*
* bind:固定綁定 es6新增
* 調(diào)用函數(shù)對(duì)象的bind方法谓着,返回一個(gè)固定this綁定的新的函數(shù)
* 對(duì)原來的函數(shù)沒有影響
*
*
*
* 優(yōu)先級(jí):bind > call,apply > new > 隱式
*/
?
?
//1、默認(rèn)綁定
function foo() {
console.log(this);//this指 obj 誰調(diào)用指向誰
}
?
?
//2坛掠、隱式綁定
var name = "Mark";
var obj = {
name : "Jack",
foo : foo,
foo1 : function () {
console.log(this.name);//this指 window
}
}
obj.foo();//{name: "Jack", foo: function, foo1: function}
var foo1 = obj.foo1;
foo1();//Mark
?
?
//3赊锚、new 綁定
function foo2() {
this.name = "Lucy";
console.log(this);//this 指向foo2 foo2 {name: "Lucy"}
}
var obj2 = new foo2();
console.log(obj2);//this 指向foo2 foo2 {name: "Lucy"}
?
var foo3 = obj.foo1;
foo3();//Mark
?
var obj3 = new foo;//foo {}
console.log(obj3);//foo {}
?
?
//4、顯示綁定
?
//call apply
function foo4(a,b) {
console.log(this.name,a,b);
}
foo4.call({name:"Jack"},10,20)//Jack 10 20
foo4.apply({name:"Mark"},[20,10])//Mark 20 10
?
//apply求max
var arr = [23,65,2,45,3,57,4567];
console.log(Math.max.apply(Math,arr)); //max = 4567
?
//定義Math 求和的方法
Math.sun = function () {
return Array.prototype.reduce.call(arguments,function (sun,ele) {
return sun + ele;
},0)
}
console.log(Math.sun.apply(Math,arr));//sum = 4762
?
//bind
var obj4 = {
name : "Jack"
}
function foo5() {
console.log(this.name);
}
var f = foo5.bind(obj4);//這種綁定方式優(yōu)先級(jí)最高
f();//Jack
?
var obj5 = {
name : "Mark",
foo6 : f
}
obj5.foo6()//Jack
</script>

2屉栓、綁定的丟失問題
<script>
/*
* 回調(diào)函數(shù)的this綁定丟失問題:this會(huì)綁定到window
*
* 定時(shí)器
*
*
* 顯示綁定丟失問題
* 顯示綁定傳入null舷蒲、undefined時(shí),this就成了默認(rèn)綁定
*
*/
?
//定時(shí)器綁定丟失
var name = "Jack";
var obj = {
name : "Mark",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向window
},1000)
}
}
obj.show();//Jack++
?
//解決方法一
var obj1 = {
name : "Mark",
show : function () {
var self = this;
setInterval(function () {
console.log(self.name);// 此時(shí)this指向obj1
},1000)
}
}
obj1.show();//Mark++
?
//解決方法二
var obj2 = {
name : "Joe",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向obj2
}.bind(this),1000)
}
}
obj2.show();//Mark++
?
//顯示綁定丟失
function foo() {
console.log(this.name);
}
var f = foo.bind(undefined);// 此時(shí)this指向window
f();//Jack
</script>

五友多、this使用總結(jié)

1牲平、this使用總結(jié)

<script>
/*
* 默認(rèn)綁定:
* 當(dāng)直接調(diào)用一個(gè)函數(shù)的時(shí)候,就是默認(rèn)綁定
* 1夷陋、非嚴(yán)格模式下欠拾,默認(rèn)綁定到window上
*
* 隱式綁定:
* 當(dāng)使用 對(duì)象.方法() 這種方式調(diào)用胰锌,稱之為隱式綁定
* this綁定到前面的那個(gè)對(duì)象上
*
* new 綁定:
* 使用new來調(diào)用構(gòu)造函數(shù)的方式
* this是綁定在新創(chuàng)建的那個(gè)對(duì)象上
*
* 顯示綁定:
* call,apply:
* 都是一錘子買賣藐窄,僅僅這一次調(diào)用的時(shí)候使用了顯示綁定资昧,對(duì)原函數(shù)沒有如何的影響
*
* call和apply的區(qū)別:就是參數(shù)的傳遞方式
* call:一個(gè)一個(gè)的傳遞
* apply:把要傳遞的參數(shù)封裝到一個(gè)數(shù)組中去傳遞
*
* bind:固定綁定 es6新增
* 調(diào)用函數(shù)對(duì)象的bind方法,返回一個(gè)固定this綁定的新的函數(shù)
* 對(duì)原來的函數(shù)沒有影響
*
*
*
* 優(yōu)先級(jí):bind > call,apply > new > 隱式
*/
?
?
//1荆忍、默認(rèn)綁定
function foo() {
console.log(this);//this指 obj 誰調(diào)用指向誰
}
?
?
//2格带、隱式綁定
var name = "Mark";
var obj = {
name : "Jack",
foo : foo,
foo1 : function () {
console.log(this.name);//this指 window
}
}
obj.foo();//{name: "Jack", foo: function, foo1: function}
var foo1 = obj.foo1;
foo1();//Mark
?
?
//3、new 綁定
function foo2() {
this.name = "Lucy";
console.log(this);//this 指向foo2 foo2 {name: "Lucy"}
}
var obj2 = new foo2();
console.log(obj2);//this 指向foo2 foo2 {name: "Lucy"}
?
var foo3 = obj.foo1;
foo3();//Mark
?
var obj3 = new foo;//foo {}
console.log(obj3);//foo {}
?
?
//4刹枉、顯示綁定
?
//call apply
function foo4(a,b) {
console.log(this.name,a,b);
}
foo4.call({name:"Jack"},10,20)//Jack 10 20
foo4.apply({name:"Mark"},[20,10])//Mark 20 10
?
//apply求max
var arr = [23,65,2,45,3,57,4567];
console.log(Math.max.apply(Math,arr)); //max = 4567
?
//定義Math 求和的方法
Math.sun = function () {
return Array.prototype.reduce.call(arguments,function (sun,ele) {
return sun + ele;
},0)
}
console.log(Math.sun.apply(Math,arr));//sum = 4762
?
//bind
var obj4 = {
name : "Jack"
}
function foo5() {
console.log(this.name);
}
var f = foo5.bind(obj4);//這種綁定方式優(yōu)先級(jí)最高
f();//Jack
?
var obj5 = {
name : "Mark",
foo6 : f
}
obj5.foo6()//Jack
</script>

2叽唱、綁定的丟失問題
<script>
/*
* 回調(diào)函數(shù)的this綁定丟失問題:this會(huì)綁定到window
*
* 定時(shí)器
*
*
* 顯示綁定丟失問題
* 顯示綁定傳入null、undefined時(shí)微宝,this就成了默認(rèn)綁定
*
*/
?
//定時(shí)器綁定丟失
var name = "Jack";
var obj = {
name : "Mark",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向window
},1000)
}
}
obj.show();//Jack++
?
//解決方法一
var obj1 = {
name : "Mark",
show : function () {
var self = this;
setInterval(function () {
console.log(self.name);// 此時(shí)this指向obj1
},1000)
}
}
obj1.show();//Mark++
?
//解決方法二
var obj2 = {
name : "Joe",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向obj2
}.bind(this),1000)
}
}
obj2.show();//Mark++
?
//顯示綁定丟失
function foo() {
console.log(this.name);
}
var f = foo.bind(undefined);// 此時(shí)this指向window
f();//Jack
</script>

五棺亭、this使用總結(jié)

1、this使用總結(jié)

<script>
/*
* 默認(rèn)綁定:
* 當(dāng)直接調(diào)用一個(gè)函數(shù)的時(shí)候蟋软,就是默認(rèn)綁定
* 1镶摘、非嚴(yán)格模式下,默認(rèn)綁定到window上
*
* 隱式綁定:
* 當(dāng)使用 對(duì)象.方法() 這種方式調(diào)用岳守,稱之為隱式綁定
* this綁定到前面的那個(gè)對(duì)象上
*
* new 綁定:
* 使用new來調(diào)用構(gòu)造函數(shù)的方式
* this是綁定在新創(chuàng)建的那個(gè)對(duì)象上
*
* 顯示綁定:
* call凄敢,apply:
* 都是一錘子買賣,僅僅這一次調(diào)用的時(shí)候使用了顯示綁定湿痢,對(duì)原函數(shù)沒有如何的影響
*
* call和apply的區(qū)別:就是參數(shù)的傳遞方式
* call:一個(gè)一個(gè)的傳遞
* apply:把要傳遞的參數(shù)封裝到一個(gè)數(shù)組中去傳遞
*
* bind:固定綁定 es6新增
* 調(diào)用函數(shù)對(duì)象的bind方法涝缝,返回一個(gè)固定this綁定的新的函數(shù)
* 對(duì)原來的函數(shù)沒有影響
*
*
*
* 優(yōu)先級(jí):bind > call,apply > new > 隱式
*/
?
?
//1、默認(rèn)綁定
function foo() {
console.log(this);//this指 obj 誰調(diào)用指向誰
}
?
?
//2譬重、隱式綁定
var name = "Mark";
var obj = {
name : "Jack",
foo : foo,
foo1 : function () {
console.log(this.name);//this指 window
}
}
obj.foo();//{name: "Jack", foo: function, foo1: function}
var foo1 = obj.foo1;
foo1();//Mark
?
?
//3拒逮、new 綁定
function foo2() {
this.name = "Lucy";
console.log(this);//this 指向foo2 foo2 {name: "Lucy"}
}
var obj2 = new foo2();
console.log(obj2);//this 指向foo2 foo2 {name: "Lucy"}
?
var foo3 = obj.foo1;
foo3();//Mark
?
var obj3 = new foo;//foo {}
console.log(obj3);//foo {}
?
?
//4、顯示綁定
?
//call apply
function foo4(a,b) {
console.log(this.name,a,b);
}
foo4.call({name:"Jack"},10,20)//Jack 10 20
foo4.apply({name:"Mark"},[20,10])//Mark 20 10
?
//apply求max
var arr = [23,65,2,45,3,57,4567];
console.log(Math.max.apply(Math,arr)); //max = 4567
?
//定義Math 求和的方法
Math.sun = function () {
return Array.prototype.reduce.call(arguments,function (sun,ele) {
return sun + ele;
},0)
}
console.log(Math.sun.apply(Math,arr));//sum = 4762
?
//bind
var obj4 = {
name : "Jack"
}
function foo5() {
console.log(this.name);
}
var f = foo5.bind(obj4);//這種綁定方式優(yōu)先級(jí)最高
f();//Jack
?
var obj5 = {
name : "Mark",
foo6 : f
}
obj5.foo6()//Jack
</script>

2害幅、綁定的丟失問題
<script>
/*
* 回調(diào)函數(shù)的this綁定丟失問題:this會(huì)綁定到window
*
* 定時(shí)器
*
*
* 顯示綁定丟失問題
* 顯示綁定傳入null消恍、undefined時(shí),this就成了默認(rèn)綁定
*
*/
?
//定時(shí)器綁定丟失
var name = "Jack";
var obj = {
name : "Mark",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向window
},1000)
}
}
obj.show();//Jack++
?
//解決方法一
var obj1 = {
name : "Mark",
show : function () {
var self = this;
setInterval(function () {
console.log(self.name);// 此時(shí)this指向obj1
},1000)
}
}
obj1.show();//Mark++
?
//解決方法二
var obj2 = {
name : "Joe",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向obj2
}.bind(this),1000)
}
}
obj2.show();//Mark++
?
//顯示綁定丟失
function foo() {
console.log(this.name);
}
var f = foo.bind(undefined);// 此時(shí)this指向window
f();//Jack
</script>

五以现、this使用總結(jié)

1狠怨、this使用總結(jié)

<script>
/*
* 默認(rèn)綁定:
* 當(dāng)直接調(diào)用一個(gè)函數(shù)的時(shí)候,就是默認(rèn)綁定
* 1邑遏、非嚴(yán)格模式下佣赖,默認(rèn)綁定到window上
*
* 隱式綁定:
* 當(dāng)使用 對(duì)象.方法() 這種方式調(diào)用,稱之為隱式綁定
* this綁定到前面的那個(gè)對(duì)象上
*
* new 綁定:
* 使用new來調(diào)用構(gòu)造函數(shù)的方式
* this是綁定在新創(chuàng)建的那個(gè)對(duì)象上
*
* 顯示綁定:
* call记盒,apply:
* 都是一錘子買賣憎蛤,僅僅這一次調(diào)用的時(shí)候使用了顯示綁定,對(duì)原函數(shù)沒有如何的影響
*
* call和apply的區(qū)別:就是參數(shù)的傳遞方式
* call:一個(gè)一個(gè)的傳遞
* apply:把要傳遞的參數(shù)封裝到一個(gè)數(shù)組中去傳遞
*
* bind:固定綁定 es6新增
* 調(diào)用函數(shù)對(duì)象的bind方法,返回一個(gè)固定this綁定的新的函數(shù)
* 對(duì)原來的函數(shù)沒有影響
*
*
*
* 優(yōu)先級(jí):bind > call,apply > new > 隱式
*/
?
?
# //1俩檬、默認(rèn)綁定
function foo() {
console.log(this);//this指 obj 誰調(diào)用指向誰
}
?
?
#//2萎胰、隱式綁定
var name = "Mark";
var obj = {
name : "Jack",
foo : foo,
foo1 : function () {
console.log(this.name);//this指 window
}
}
obj.foo();//{name: "Jack", foo: function, foo1: function}
var foo1 = obj.foo1;
foo1();//Mark
?
?
# //3、new 綁定
function foo2() {
this.name = "Lucy";
console.log(this);//this 指向foo2 foo2 {name: "Lucy"}
}
var obj2 = new foo2();
console.log(obj2);//this 指向foo2 foo2 {name: "Lucy"}
?
var foo3 = obj.foo1;
foo3();//Mark
?
var obj3 = new foo;//foo {}
console.log(obj3);//foo {}
?
?
# //4棚辽、顯示綁定
?
//call apply
function foo4(a,b) {
console.log(this.name,a,b);
}
foo4.call({name:"Jack"},10,20)//Jack 10 20
foo4.apply({name:"Mark"},[20,10])//Mark 20 10
?
//apply求max
var arr = [23,65,2,45,3,57,4567];
console.log(Math.max.apply(Math,arr)); //max = 4567
?
//定義Math 求和的方法
Math.sun = function () {
return Array.prototype.reduce.call(arguments,function (sun,ele) {
return sun + ele;
},0)
}
console.log(Math.sun.apply(Math,arr));//sum = 4762
?
//bind
var obj4 = {
name : "Jack"
}
function foo5() {
console.log(this.name);
}
var f = foo5.bind(obj4);//這種綁定方式優(yōu)先級(jí)最高
f();//Jack
?
var obj5 = {
name : "Mark",
foo6 : f
}
obj5.foo6()//Jack
</script>

2技竟、綁定的丟失問題

<script>
/*
* 回調(diào)函數(shù)的this綁定丟失問題:this會(huì)綁定到window
*
* 定時(shí)器
*
*
* 顯示綁定丟失問題
* 顯示綁定傳入null、undefined時(shí)屈藐,this就成了默認(rèn)綁定
*
*/
?
//定時(shí)器綁定丟失
var name = "Jack";
var obj = {
name : "Mark",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向window
},1000)
}
}
obj.show();//Jack++
?
//解決方法一
var obj1 = {
name : "Mark",
show : function () {
var self = this;
setInterval(function () {
console.log(self.name);// 此時(shí)this指向obj1
},1000)
}
}
obj1.show();//Mark++
?
//解決方法二
var obj2 = {
name : "Joe",
show : function () {
setInterval(function () {
console.log(this.name);// 此時(shí)this指向obj2
}.bind(this),1000)
}
}
obj2.show();//Mark++
?
//顯示綁定丟失
function foo() {
console.log(this.name);
}
var f = foo.bind(undefined);// 此時(shí)this指向window
f();//Jack
</script>

5.3 for循環(huán)典型問題

看下面的代碼

<body>
<input type="button" value="按鈕1" >
<input type="button" value="按鈕2" >
<input type="button" value="按鈕3" >
<script type="text/javascript">
var btns = document.getElementsByTagName("input");
for (var i = 0; i < 3; i++) {
btns[i].onclick = function () {
alert("我是第" + (i + 1) + "個(gè)按鈕");
};
}
</script>
</body>

發(fā)現(xiàn)在點(diǎn)擊三個(gè)按鈕的時(shí)候都是彈出 我是第4個(gè)按鈕榔组。 為什么呢?閉包導(dǎo)致的联逻! 每循環(huán)一次都會(huì)有一個(gè)匿名函數(shù)設(shè)置點(diǎn)擊事件搓扯,閉包總是保持的變量的最后一個(gè)值,所以點(diǎn)擊的時(shí)候包归,總是讀的是 i 的組后一個(gè)值4.

解決方案1:給每個(gè)按鈕添加一個(gè)屬性锨推,來保存 每次 i 的臨時(shí)值

<body>
<input type="button" value="按鈕1" >
<input type="button" value="按鈕2" >
<input type="button" value="按鈕3" >
<script type="text/javascript">
var btns = document.getElementsByTagName("input");
for (var i = 0; i < 3; i++) {
//把i的值綁定到按鈕的一個(gè)屬性上,那么以后i的值就和index的值沒有關(guān)系了公壤。
btns[i].index = i;
btns[i].onclick = function () {
alert("我是第" + (this.index + 1) + "個(gè)按鈕");
};
}
</script>
</body>

解決方案2:使用匿名函數(shù)的自執(zhí)行

<body>
<input type="button" value="按鈕1" >
<input type="button" value="按鈕2" >
<input type="button" value="按鈕3" >
<script type="text/javascript">
var btns = document.getElementsByTagName("input");
for (var i = 0; i < 3; i++) {
//因?yàn)槟涿瘮?shù)已經(jīng)執(zhí)行了爱态,所以會(huì)把 i 的值傳入到num中,注意是i的值境钟,所以num
(function (num) {
btns[i].onclick = function () {
alert("我是第" + (num + 1) + "個(gè)按鈕");
}
})(i);
}
</script>
</body>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市俭识,隨后出現(xiàn)的幾起案子慨削,更是在濱河造成了極大的恐慌,老刑警劉巖套媚,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缚态,死亡現(xiàn)場離奇詭異,居然都是意外死亡堤瘤,警方通過查閱死者的電腦和手機(jī)玫芦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來本辐,“玉大人桥帆,你說我怎么就攤上這事∩髦澹” “怎么了老虫?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茫多。 經(jīng)常有香客問我祈匙,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任夺欲,我火速辦了婚禮跪帝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘些阅。我一直安慰自己伞剑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布扑眉。 她就那樣靜靜地躺著纸泄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腰素。 梳的紋絲不亂的頭發(fā)上聘裁,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音弓千,去河邊找鬼衡便。 笑死,一個(gè)胖子當(dāng)著我的面吹牛洋访,可吹牛的內(nèi)容都是我干的镣陕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼姻政,長吁一口氣:“原來是場噩夢啊……” “哼呆抑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汁展,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤鹊碍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后食绿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侈咕,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年器紧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耀销。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铲汪,死狀恐怖熊尉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情桥状,我是刑警寧澤帽揪,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站辅斟,受9級(jí)特大地震影響转晰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一查邢、第九天 我趴在偏房一處隱蔽的房頂上張望蔗崎。 院中可真熱鬧,春花似錦扰藕、人聲如沸缓苛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽未桥。三九已至,卻和暖如春芥备,著一層夾襖步出監(jiān)牢的瞬間冬耿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工萌壳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亦镶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓袱瓮,卻偏偏與公主長得像缤骨,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子尺借,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理绊起,服務(wù)發(fā)現(xiàn),斷路器燎斩,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 一勒庄、你不知道的JavaScript 1、作用域 作用域 LHS RHS RHS查詢與簡單地查找某個(gè)變量的值別無二...
    頂兒響叮當(dāng)閱讀 345評(píng)論 0 0
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line)瘫里,也就是一...
    悟名先生閱讀 4,131評(píng)論 0 13
  • 如何控制alert中的換行?\n alert(“p\np”); 請(qǐng)編寫一個(gè)JavaScript函數(shù) parseQu...
    heyunqiang99閱讀 1,084評(píng)論 0 6
  • 1荡碾、使用typeof bar ===“object”來確定bar是否是一個(gè)對(duì)象時(shí)有什么潛在的缺陷谨读?這個(gè)陷阱如何避免...
    深海鯽魚堡閱讀 659評(píng)論 1 1