問題 什麼是構造函數?構造函數與普通函數區別是什麼?用new關鍵字的時候到底做了什麼?構造函數有返回值怎麼辦?構造函數能當普通函數調用嗎? thisthis永遠指向當前正在被執行的函數或方法的owner。例如: 1 2 3 4 5 function test(){ console.log(this) ...
問題
什麼是構造函數?
構造函數與普通函數區別是什麼?
用new關鍵字的時候到底做了什麼?
構造函數有返回值怎麼辦?
構造函數能當普通函數調用嗎?
this
this永遠指向當前正在被執行的函數或方法的owner。例如:
1 2 3 4 5 |
function test(){
console.log( this );
}
test();
//Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
|
上面這段代碼中,我們在頁面中定義了一個test()函數,然後在頁面中調用。函數定義在全局時,其owner就是當前頁面,也就是window對象。
this指向的幾種情況
1.全局中調用
this.name //this指向window對象
2.函數調用
test();//test()函數中的this也指向window對象
3.對象的方法調用
obj1.fn();//obj1對象的fn()方法中的this指向obj1
4.調用構造函數
var dog=new Dog();//構造函數內的this指向新創建的實例對象,也就是這裡的dogcall和apply
call和apply的作用一樣,只是接受參數的方式不一樣,call接受的是多個單個參數,apply接受的是參數數組。
call和apply的作用簡單地可以說成,當一個對象實例缺少一個函數/方法時,可以調用其他對象的現成函數/方法,其方式是通過替換其中的this為這個對象實例,改變函數運行時的上下文。
例如:
1 2 3 4 5 6 |
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);
加點東西,變成一個帶參數的例子:
1 2 3 4 5 6 7 8 9 |
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:喵喵喵 餓了
|
普通函數
這是一個簡單的普通函數:
1 2 3 4 |
function fn(){
alert( "hello sheila" );
}
fn(); //alert:hello sheila
|
普通函數與構造函數相比有四個明顯特點:
1.不需要用new關鍵字調用
fn();2.可以用return語句返回值
1 2 3 4 |
function fn(a,b){
return a+b;
}
alert(fn(2,3)); //alert:5
|
3.函數內部不建議使用this關鍵字
我們說不建議使用,當然硬要用是可以的,只是要註意這時候發生了什麼。如果在普通函數內部使用this關鍵字定義變數或函數,因為這時候this指向的是window全局對象,這樣無意間就會為window添加了一些全局變數或函數。
1 2 3 4 5 6 |
function greeting(){
this .name= "sheila" ;
alert( "hello " + this .name);
}
greeting(); //alert:hello sheila
alert(window.name); //alert:sheila
|
4.函數命名以駝峰方式,首字母小寫
構造函數
在JavaScript中,用new關鍵字來調用定義的構造函數。預設返回的是一個新對象,這個新對象具有構造函數定義的變數和函數/方法。
舉個例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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語句的返回值。
1 2 3 4 5 6 7 |
function Person(name){
this .name=name;
return {name: "cherry" }
}
var person= new Person( "sheila" );
person.name; //cherry
p; //Object {name: "cherry"}
|