JavaScript中的普通函數與構造函數

問題

什麼是構造函數?
構造函數與普通函數區別是什麼?
用new關鍵字的時候到底作了什麼?
構造函數有返回值怎麼辦?
構造函數能當普通函數調用嗎?chrome

如下是個人一些理解,理解錯誤的地方懇請你們幫忙指正,謝謝!數組

this

this永遠指向當前正在被執行的函數或方法的owner。例如:app

function test(){
    console.log(this);
}
test();//Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

上面這段代碼中,咱們在頁面中定義了一個test()函數,而後在頁面中調用。函數定義在全局時,其owner就是當前頁面,也就是window對象。函數

this指向的幾種狀況

1.全局中調用this

this.name //this指向window對象

2.函數調用prototype

test();//test()函數中的this也指向window對象

3.對象的方法調用code

obj1.fn();//obj1對象的fn()方法中的this指向obj1

4.調用構造函數對象

var dog=new Dog();//構造函數內的this指向新建立的實例對象,也就是這裏的dog

call和apply

call和apply的做用同樣,只是接受參數的方式不同,call接受的是多個單個參數,apply接受的是參數數組。
call和apply的做用簡單地能夠說成,當一個對象實例缺乏一個函數/方法時,能夠調用其餘對象的現成函數/方法,其方式是經過替換其中的this爲這個對象實例,改變函數運行時的上下文。
例如:ip

function Dog(){
    this.sound="汪汪汪";
}
Dog.prototype.bark=function(){
    alert(this.sound);
}

如今我有另一個cat對象:原型

var cat={sound:'喵喵喵'}

我也想讓這個cat對象能夠調用bark方法,這時候就不用從新爲它定義bark方法了,能夠用call/apply調用Dog類的bark方法:

Dog.prototype.bark.call(cat);

或者:

dog.bark.call(cat);

加點東西,變成一個帶參數的栗子:

function Dog(){
    this.sound="汪汪汪";
}
Dog.prototype.bark=function(words){
    alert(this.sound+"  "+words);
}
var dog=new Dog();
dog.bark("有小偷");//alert:汪汪汪   有小偷
Dog.prototype.bark.call(cat,"餓了");//alert:喵喵喵   餓了

普通函數

這是一個簡單的普通函數:

function fn(){
    alert("hello sheila");
}
fn();//alert:hello sheila

普通函數與構造函數相比有四個明顯特色:

1.不須要用new關鍵字調用

fn();

2.能夠用return語句返回值

function fn(a,b){
        return a+b;
    }
    alert(fn(2,3));//alert:5

3.函數內部不建議使用this關鍵字
咱們說不建議使用,固然硬要用是能夠的,只是要注意這時候發生了什麼。若是在普通函數內部使用this關鍵字定義變量或函數,由於這時候this指向的是window全局對象,這樣無心間就會爲window添加了一些全局變量或函數。

function greeting(){
        this.name="sheila";
        alert("hello "+this.name);
    }
    greeting();//alert:hello sheila
    alert(window.name);//alert:sheila

4.函數命名以駝峯方式,首字母小寫

構造函數

在JavaScript中,用new關鍵字來調用定義的構造函數。默認返回的是一個新對象,這個新對象具備構造函數定義的變量和函數/方法。

舉個栗子:

function Prince(name,age){
    this.gender="male";
    this.kind=true;
    this.rich=true;
    this.name=name;
    this.age=age;
}
Prince.prototype.toFrog=function(){
    console.log("Prince "+this.name+" turned into a frog.");
}
var prince=new Prince("charming",25);
prince.toFrog();//Prince charming turned into a frog.
prince.kind;//true

與普通函數相比,構造函數有如下明顯特色:

1.用new關鍵字調用

var prince=new Prince("charming",25);

2.函數內部可使用this關鍵字
在構造函數內部,this指向的是構造出的新對象。用this定義的變量或函數/方法,就是實例變量或實例函數/方法。須要用實例才能訪問到,不能用類型名訪問。

prince.age;//25
    Prince.age;//undefined

3.默認不用return返回值
構造函數是不須要用return顯式返回值的,默認會返回this,也就是新的實例對象。固然,也能夠用return語句,返回值會根據return值的類型而有所不一樣,細節將在下文介紹。

4.函數命名建議首字母大寫,與普通函數區分開。
不是命名規範中的,可是建議這麼寫。

使用new關鍵字實例化的時候發生了什麼?

以上文中的Prince()函數舉個栗子:

1.第一步,建立一個空對象。

var prince={}

2.第二步,將構造函數Prince()中的this指向新建立的對象prince。
3.第三步,將prince的_proto_屬性指向Prince函數的prototype,建立對象和原型間關係
4.第四步,執行構造函數Prince()內的代碼。

構造函數有return值怎麼辦?

構造函數裏沒有顯式調用return時,默認是返回this對象,也就是新建立的實例對象。
當構造函數裏調用return時,分兩種狀況:

1.return的是五種簡單數據類型:String,Number,Boolean,Null,Undefined。
這種狀況下,忽視return值,依然返回this對象。

2.return的是Object
這種狀況下,再也不返回this對象,而是返回return語句的返回值。

function Person(name){
        this.name=name;
        return {name:"cherry"}
    }
    var person=new Person("sheila");
    person.name;//cherry
    person;//Object {name: "cherry"}
相關文章
相關標籤/搜索