摘要:在函數中調用時指向調用函數的對象,調用函數的在不同情況下有直接調用,此時函數內部的指向全局對象作為對象的方法,此時指向該對象構造函數,此時指向構造的實例對象改變指向是語言的一個關鍵字。但是有一個總的原則,那就是指的是,調用函數的那個對象。
this在全局中調用時指向的是全局對象。
this在函數中調用時指向調用函數的對象,調用函數的在不同情況下有
1.直接調用,此時函數內部的this指向全局對象 2.作為對象的方法,此時this指向該對象 3.構造函數,此時this指向構造的實例對象 4.call/apply改變this指向
this是Javascript語言的一個關鍵字。
它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用。比如,
function test(){ this.x = 1; }
隨著函數使用場合的不同,this的值會發生變化。但是有一個總的原則,那就是this指的是,調用函數的那個對象。
下面分四種情況,詳細討論this的用法。
這是函數的最通常用法,屬于全局性調用,因此this就代表全局對象global/window(在瀏覽器中全局對象即頂層對象指的是window,在nodejs中全局對象指的是global)。
請看下面這段代碼,它的運行結果是1。
function test(){ this.x = 1; alert(this.x); alert(this === window); test(); // 1 //true
為了證明this就是全局對象,我對代碼做一些改變:
var x = 1; function test(){ alert(this.x); } test(); // 1
運行結果還是1。再變一下:
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
當調用函數test()后,執行this.x 語句,而這里的this.x指向的是全局的x,所以全局的x=1在這個時候變成x=0,所以在最后alert(x)的時候數據0。
從這里可以看出函數里的 this.x 指的是全局變量x里吧。
那如果是帶有參數的函數呢?再來看看下面的例子:
var a = 20; function fun(a){ this.a = 1; console.log(a); console.log(this.a); }; fun(10); //10 //1
當函數帶有參數時,this依舊指向全局的變量,與參數沒有任何關系,上面的寫法就類似于下面的這種寫法。
var a = 20; function fun(b){ this.a = 1; console.log(b); console.log(this.a); }; fun(10); //10 //1
如果把this.a改成this.b呢?那this.b指向的是全局的變量還是函數里面的變量呢?
var a = 20; function fun(b){ this.b = 1; //沒有用var 相當于定義了一個全局變量b,并賦值為1 console.log(b); //10 打印出傳入的參數b console.log(this.b); //1 打印出全局變量b }; fun(10); console.log(b); //1 打印出全局變量b
JavaScript里規定,全局函數里沒有用var定義的的變量是全局變量,所以這里的this.b就相當于定義了一個全局的變量b,所以在最后能打印出變量b
現在你能看懂下面兩個函數了吧
var a = 20; function fun(a){ this.a = 1; console.log(a) }; console.log(a);//20 沒有執行this.a=1 語句時,全局變量a依舊為20 fun(10);//10 var a = 20; function fun(a){ this.a = 1; console.log(a) }; fun(10);//10 console.log(a);//1 執行this.a=1 語句后,全局變量a變為1情況二:作為對象方法的調用
函數還可以作為某個對象的方法調用,這時this就指這個上級對象。
function test(){ alert(this.x); } var o = {}; o.x = 1; o.m = test; o.m(); // 1
或者用對象字面量來創建方法是好理解些,但都是一個意思
var pet = { words : "my dear", speak : function(){ console.log(this.words); //my dear console.log(this === pet); //true } } pet.speak();情況三 作為構造函數調用
所謂構造函數,就是通過這個函數生成一個新對象(object)。這時,this就指這個新對象。
function test(){ this.x = 1; } var o = new test(); alert(o.x); // 1
運行結果為1。為了表明這時this不是全局對象,我對代碼做一些改變:
var x = 2; function test(){ this.x = 1; } var o = new test(); alert(x); //2
運行結果為2,表明全局變量x的值根本沒變。
再來看一個在實際應用中的例子
function Pet(words){ this.words = words; this.speak = function(){ console.log(this.words); console.log(this) } } var cat = new Pet("Miao"); cat.speak(); //當nwe了一個實例對象cat后,cat擁有了自己的word屬性和speak方法,而cat.speak()調用時this指的的是cat對象自己 // Miao //Pet { words: "Miao", speak: [Function] }情況四 apply、call調用
apply()是函數對象的一個方法,它的作用是改變函數的調用對象,它的第一個參數就表示改變后的調用這個函數的對象。因此,this指的就是這第一個參數。
var x = 0;
function test(){
alert(this.x);
}
var o={};
o.x = 1;
o.m = test;
o.m.apply(); //0
apply()的參數為空時,默認調用全局對象。因此,這時的運行結果為0,證明this指的是全局對象。
如果把最后一行代碼修改為
o.m.apply(o); //1
運行結果就變成了1,證明了這時this代表的是對象o。
apply有兩種實際的應用場景:
1.在對象中--調用時才改變this指向,如上例子,也許下面的例子好理解些
var pet = { words : "my dear", speak : function(say){ console.log(say + " " +this.words) } } pet.speak("hello");//hello my dear //利用apple調用時改變this的指向 var dog = { words :"wang" } pet.speak.call(dog,"hello");//hello wang pet.speak("hello")//hello my dear
2.實現繼承時的構造函數--定義時改變this指向
function Pets(words,sex){ this.words = words; this.sex = sex; this.speak = function(){ console.log(this.words + " " + this.sex) } } function Dog(words,sex){ //Pets.call(this, words, sex); //Pets.apply(this,[words, sex]) Pets.apply(this,arguments) } var dog = new Dog("wang","girl") dog.speak();//wang,girl
參考資料:
1.《JavaScript的this用法》--阮一峰
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90135.html
摘要:面向對象面向對象編程的全稱是,簡稱,面向對象編程是用抽象方式創建基于現實世界模型的一種編程模式。面向對象編程的三個主要特征是封裝繼承多態。 面向對象 面向對象編程的全稱是Object Oriented Programming,簡稱OOP,面向對象編程是用抽象方式創建基于現實世界模型的一種編程模式。面向對象編程可以看做是使用一系列對象相互協作的軟件設計,面向對象程序設計的目的是在編程中促...
摘要:組合方式實現繼承原型鏈構造函數喵喵喵汪汪汪與的唯一區別是多了這一句組合方式實現了對構造函數內和原型上所有屬性和方法的繼承,并且的實例對象之間也不會相互干擾。 前言 關于JavaScript繼承相關的定義和方法網上已經有很多解釋啦,本菜鳥就不抄抄寫寫惹人嫌了,本文主要探討三種基本的繼承方式并且給出優化方案。 正文 借助構造函數實現繼承 function Parent1() { ...
摘要:綁定使用方式進行調用函數時,會發生構造函數的調用。先上圖,然后根據文字閱讀使用調用函數之后,該函數才作為構造函數進行調用,構造一個全新的對象賦值給,而對象的指向了的對象,的對象有一個屬性指向的構造函數這個就是的原型鏈,也是的特性。 javascript語言是在運行時前即進行編譯的,而this的綁定也是在運行時進行綁定的。也就是說,this實際上是在函數被調用時候發生綁定的,它指向什么完...
摘要:在這其中我們就逃不開要討論繼承原型對象構造函數實例了。想要獲得某一類型的構造函數可以用來獲得,也可以對該屬性進行賦值操作。三上面就提到一點是指構造函數的原型對象,它是一個對象,它是構造函數的屬性。 原型鏈這一個話題,需要和很多概念一起講,才能串成一個比較系統的知識點。在這其中我們就逃不開要討論繼承、原型對象、構造函數、實例了。 一、構造函數 構造函數是一類特殊的函數,它的作用是用來生成...
摘要:工廠模式優點集中實例化,可以傳參等缺點分不清屬于哪個對象我們先來談談優點,看例子集中實例化返回實例化對象返回返回不難看出,工廠模式比上面的例子減少了很多代碼。 ECMAscript開發的兩種模式:1.過程化 2.OOP(面向對象) 面向對象的語言有一個標志,那就是類的概念,而通過類可以創建任意多個具有相同屬性的方法的對象。但是ECMAscript中沒有類的概念! 又談作用域 首先...
摘要:構造函數上一章我們講了工廠模式,它的缺點就是無法識別到底哪個屬于哪個的問題。我們可以用構造函數來解決這個識別問題。來比較構造函數內的值就可以看出到底是什么類型。 構造函數 上一章我們講了工廠模式,它的缺點就是無法識別到底哪個屬于哪個的問題。我們可以用構造函數來解決這個識別問題。 //構造函數 function Create(a,b) { this.a =a; this...
閱讀 1702·2021-11-18 10:02
閱讀 2218·2021-11-15 11:38
閱讀 2666·2019-08-30 15:52
閱讀 2190·2019-08-29 14:04
閱讀 3231·2019-08-29 12:29
閱讀 2086·2019-08-26 11:44
閱讀 994·2019-08-26 10:28
閱讀 830·2019-08-23 18:37