国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript中的this使用詳解

2019-11-20 09:24:39
字體:
來源:轉載
供稿:網友

其實this是一個老生常談的問題了。關于this的文章非常多,其實我本以為自己早弄明白了它,不過昨天在做項目的過程中,還是出現了一絲疑惑,想到大概之前在JavaScript weekly里收藏待看的一篇詳解this的文章(后有鏈接,也附上了稀土上的中文譯文)和另一篇一位前輩推薦的文章,就把它們看了看,對this的認識確實提升了一些。

JavaScript 中的'this‘是動態的,它在函數運行時被確定而非在函數聲明時被確定。所有的函數都可以調用'this',這無關于該函數是否屬于某個對象。關于this,主要有以下四種情況。

1.被當做對象的方法被調用

如果該函數是被當做某一個對象的方法,那么該函數的this指向該對象;

  var john = {   firstName: "John"  }  function func() {   alert(this.firstName + ": hi!")  }  john.sayHi = func  john.sayHi() // this = john

這里有一點值得注意,當一個對象的方法被取出來賦值給一個變量時,該方法變為函數觸發,this指向window或underfind(嚴格模式)。

2.函數之內調用

當函數中有 this,其實就意味著它被當做方法調用,之間調用相當于把他當做window對象的方法,this指向window,值得注意的是ES5其實是規定這種情況this=undefined的,只瀏覽器大多還是按照老的方法執行(本人在最新版的Chrome,Safari,Firefox中測試都指向window(201607)),在火狐下使用嚴格模式指向undefined;

  func()  function func() {    alert(this) // [object Window] or [object global] or kind of..  }

為了傳遞this,()之前應該為引用類型,類似于obj.a 或者 obj['a'],不能是別的了。

這里還存在一個小坑,當對象的方法中還存在函數時,該函數其實是當做函數模式觸發,所以其this默認為window(嚴格模式下為undefined)解決辦法是給該函數綁定this。

var numbers = {   numberA: 5,  numberB: 10,  sum: function() {   console.log(this === numbers); // => true   function calculate() {    // this is window or undefined in strict mode    console.log(this === numbers); // => false    return this.numberA + this.numberB;   }   return calculate();  }};numbers.sum(); // => NaN or throws TypeError in strict mode var numbers = {   numberA: 5,  numberB: 10,  sum: function() {   console.log(this === numbers); // => true   function calculate() {    console.log(this === numbers); // => true    return this.numberA + this.numberB;   }   // use .call() method to modify the context   return calculate.call(this);  }};numbers.sum(); // => 15 

3.在new中調用

一個引用對象的變量實際上保存了對該對象的引用,也就是說變量實際保存的是對真實數據的一個指針。
使用new關鍵字時this的改變其實有以下幾步:

創建 this = {}.
new執行的過程中可能改變this,然后添加屬性和方法;
返回被改變的this.

  function Animal(name) {    this.name = name    this.canWalk = true  }  var animal = new Animal("beastie")  alert(animal.name)

需要注意的是如果構造函數返回一個對象,那么this指向返回的那個對象;

  function Animal() {    this.name = 'Mousie';    this.age = '18';    return {      name: 'Godzilla'    } // <-- will be returned  }  var animal = new Animal()  console.log(animal.name) // Godzilla  console.log(animal.age)//undefined

這里需要注意的是不要忘記使用new,否則不會創建一個新的函數。而是只是執行了函數,相當于函數調用,this其實指向window

function Vehicle(type, wheelsCount) {  this.type = type; this.wheelsCount = wheelsCount; return this;}// Function invocationvar car = Vehicle('Car', 4); car.type;    // => 'Car' car.wheelsCount // => 4 car === window // => true

4.明確調用this,使用call和apply

這是最具JavaScript特色的地方。
如下代碼:

func.call(obj, arg1, arg2,...)

第一個參數將作為this的指代對象,之后的參數將被作為函數的參數,解決方法是使用bind。

function Animal(type, legs) {  this.type = type; this.legs = legs;  this.logInfo = function() {  console.log(this === myCat); // => true  console.log('The ' + this.type + ' has ' + this.legs + ' legs'); };}var myCat = new Animal('Cat', 4); // logs "The Cat has 4 legs"setTimeout(myCat.logInfo.bind(myCat), 1000); // setTimeout?? var john = {  firstName: "John",  surname: "Smith" } function func(a, b) {  alert( this[a] + ' ' + this[b] ) } func.call(john, 'firstName', 'surname') // "John Smith"

至于apply,其只是以數組的方傳入參數,其它部分是一樣的,如下:

 func.call(john, 'firstName', 'surname') func.apply(john, ['firstName', 'surname'])

它們也可用于在 ES5 中的類繼承中,調用父級構造器。

  function Runner(name) {    console.log(this instanceof Rabbit); // => true   this.name = name;   }  function Rabbit(name, countLegs) {    console.log(this instanceof Rabbit); // => true   // 間接調用,調用了父級構造器   Runner.call(this, name);   this.countLegs = countLegs;  }  var myRabbit = new Rabbit('White Rabbit', 4);   myRabbit; // { name: 'White Rabbit', countLegs: 4 }

5..bind()

對比方法 .apply() 和 .call(),它倆都立即執行了函數,而 .bind() 函數返回了一個新方法,綁定了預先指定好的 this ,并可以延后調用。

.bind() 方法的作用是創建一個新的函數,執行時的上下文環境為 .bind() 傳遞的第一個參數,它允許創建預先設置好 this 的函數。

var numbers = {  array: [3, 5, 10], getNumbers: function() {  return this.array;   }};// Create a bound functionvar boundGetNumbers = numbers.getNumbers.bind(numbers); boundGetNumbers(); // => [3, 5, 10] // Extract method from objectvar simpleGetNumbers = numbers.getNumbers; simpleGetNumbers(); // => undefined or throws an error in strict mode 

使用.bind()時應該注意,.bind() 創建了一個永恒的上下文鏈并不可修改。一個綁定函數即使使用 .call() 或者 .apply()傳入其他不同的上下文環境,也不會更改它之前連接的上下文環境,重新綁定也不會起任何作用。

只有在構造器調用時,綁定函數可以改變上下文,然而這并不是特別推薦的做法。

6.箭頭函數

箭頭函數并不創建它自身執行的上下文,使得 this 取決于它在定義時的外部函數。

箭頭函數一次綁定上下文后便不可更改,即使使用了上下文更改的方法:

  var numbers = [1, 2];   (function() {    var get = () => {    console.log(this === numbers); // => true    return this;   };   console.log(this === numbers); // => true   get(); // => [1, 2]   // 箭頭函數使用 .apply() 和 .call()   get.call([0]); // => [1, 2]   get.apply([0]); // => [1, 2]   // Bind   get.bind([0])(); // => [1, 2]  }).call(numbers);

這是因為箭頭函數擁有靜態的上下文環境,不會因為不同的調用而改變。因此不要使用箭頭函數定義方法

function Period (hours, minutes) {    this.hours = hours;   this.minutes = minutes;  }  Period.prototype.format = () => {    console.log(this === window); // => true   return this.hours + ' hours and ' + this.minutes + ' minutes';  };  var walkPeriod = new Period(2, 30);   walkPeriod.format(); // => 'undefined hours and undefined minutes'

參考

Four scents of "this"

Gentle explanation of 'this' keyword in JavaScript

JavaScript This 之謎(譯文)

強烈推薦覺得沒弄明白的同學看看上面三篇文章,其中第三篇是第二篇的譯文。如果大家對this還有疑問,也歡迎大家一起討論,交流促進思考,共同進步。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 灯塔市| 西乡县| 西和县| 霍邱县| 尼玛县| 鄂托克旗| 察隅县| 信丰县| 黔西县| 安福县| 房产| 漳州市| 册亨县| 定日县| 许昌县| 大关县| 凉城县| 朔州市| 河东区| 太仆寺旗| 宁海县| 三明市| 商都县| 错那县| 景德镇市| 奉化市| 延安市| 旺苍县| 安义县| 平顺县| 南召县| 时尚| 凭祥市| 横峰县| 页游| 正镶白旗| 安泽县| 平山县| 石柱| 阿勒泰市| 江阴市|