關於js構造函數中this的指向


先來一道開胃菜:

function person(name) {
            // 變量作用域為函數內部,外部無法訪問,防止了變量名沖突和污染
            var name = '小明';
            this.name = name;
            this.sayName = function() {
                console.log(name);
            }
            this.changeName = function(newName) {
                name = newName;
            }
        }
        // 外部無法訪問內部變量
        var a = new person();
        console.log(a.name)
運行一下

首先JS里沒有類.
構造函數是個函數,this指向的是個對象,this蒙上眼睛指也指不到構造函數去.
構造函數的this指向創建的實例對象無疑. 要明白這一點,要先弄明白,用new操作符調用構造函數的時候都發生了什么.
正好我有個答案是講構造函數的, 我這里原樣搬來:

造函數其實和普通函數本質上並無區別,唯一的區別有兩個:

函數首字母大寫,這個區別只是約定俗成的,便於區分。你實在要小寫定義構造函數也完全沒問題,所以這個區別可以忽略。

構造函數的調用需要用new操作符,而普通函數的調用又分很多種,但是都不會用到new操作符。所以,構造函數和普通函數的區別就在這個new操作符里,現在讓我們來好好研究一下這個new操作符。
用new操作符創建對象時發生的事情:

**第一步: 創建一個Object對象實例。
第二步: 將構造函數的執行對象賦給新生成的這個實例。
第三步: 執行構造函數中的代碼
第四步: 返回新生成的對象實例**

注意:原本的構造函數是window對象的方法,如果不用new操作符而直接調用,那么構造函數的執行對象就 是window,即this指向了window。現在用new操作符后,this就指向了新生成的對象。理解這一步至關重要。
執行構造函數中的代碼,看代碼:

function Person(){
this.name = "Tiny Colder";
var age = 22;
window.age = 22;
}
var p = new Person();
alert(p.name)//Tiny Colder;
alert(p.age)//undefined;
alert(window.age)//22;

當用new操作符創建對象時,先創建了一個對象實例,然后執行代碼。所以還在糾結,什么時候構造函數定義的屬性會繼承給實例對象的,都可以這么來看:

var p = new Object();
p.name = "Tiny Colder";

這是普通的創建對象,然后給對象添加屬性的方法。如果每創建一個對象,都需要這么幾行代碼,無疑是糟糕的。這個需求就正好跟這一點對應:new操作符,自動執行構造函數里的代碼。如此我們便可以省掉添加屬性時重復冗余的代碼。那么這些屬性時如何添加到新生成的對象里的呢?

第二個步驟里已經說了:將構造函數的執行對象賦給新生成的這個實例。再結合上一段里說的,自動執行構造函數里的this.name = "Tiny Colder";時,就相當於是執行p.name = "Tiny Colder";而構造函數里的
var age = 22;語句,會執行但是對新生成的對象並無影響。window.age = 22;語句,會執行,且會給window對象添加一個屬性。alert為證。

或許到這里,你已經理解了new操作符的前三步了,重要的三步。但是這個函數是如何返回對象的呢?我們並沒有看到有任何跟return相關的語句。這就是new操作符的最后一步:返回新生成的對象。
如果被調用的函數沒有顯式的 return 表達式(僅限於返回對象),則隱式的會返回 this 對象 - 也就是新創建的對象。

現在來看一下這個代碼:

function Person(){
this.name = "Tiny Colder";
return {};
}
var p = new Person();
alert(p.name)//undefined;

一個對象就這么被創建出來了。
實際上,

var p = new Person();

var p = new Object();
Person.apply(p);

是一樣的效果。

 

簡單的總結:

顯式的返回以下值:undefined, null, boolean, number等基礎類型,並不會代替 new 式調用的默認行為。

但顯式返回以下值:{},[],RegExp, Date, Function,均會代替 new 調用的默認返回值 this.

大家都看到了,后者,全都是 對象,是復雜類型。

 

如果函數體是嚴格模式,則不會綁定 this 至全局對象,如:

var  a =  function  (){ 'use strict' ; this .b =  'b' return  /111/g};
a();  // 直接報錯
因為嚴格模式下,默認的 this 指向 undefined


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM