深刻理解Javascript中this, prototype, constructor

在Javascript面向對象編程中常常須要使用到this,prototype和constructor這3個關鍵字.編程

1.首先介紹一下this的使用:this表示當前對象;若是在全局中使用this,則this爲當前頁面對象window;若是在函數中使用this,則this爲調用該函數的對象;可使用apply和call兩個全局函數來改變this的指向。數組

接下來,首先經過幾個demo程序驗證一下:app

function testFunction(){

    console.log(this.variable);
};

var variable='Global Variable';

testFunction();

var packObject={variable:'Pack variable',testFunction:testFunction};

packObject.testFunction();
View Code

接下來經過Demo驗證一下如何使用apply和call函數來改變this的指向:ide

function testFunction(){
    console.log(this.variabale);
};

var variable='Global Variable';

var packObject={variable:'Pack Variable'};

testFunction.apply(window);

testFunction.apply(packObject);


testFunction.call(window);

testFunction.call(packObject);
View Code

接下來在經過Demo演示一下函數對象的使用:函數

function testFunction(){
    if(this===window){
        console.log('This is window');
    }
};


testFunction.innerFunction=function(){
    if(this===testFunction){
        console.log('This is testFunction');
    }
    if(this===window){
        console.log('This is window');
    }
};

///
/// 等價於:window.testFunction();
///
testFunction();

testFunction.innerFunction();

testFunction.innerFunction.apply(window);
testFunction.innerFunction.call(window);
View Code

2.接下來介紹一下什麼是原型(prototype):this

prototype本質上仍是Javascript的一個對象;每一個函數都有一個默認的prototype屬性;經過prototype能夠擴展Javascript中的內建對象。spa

接下來經過Demo展現一下如何使用prototype:prototype

function Person(name){
    this.name=name;
};

Person.prototype={
    getName:function(){
        return this.name;
    }
};

var testPerson=Person('test name');

console.log(testPerson.getName());
View Code

讓咱們來嘗試一下如何使用prototype擴展Javascript內建對象:3d

Array.prototype.min=function(){
    var min=this[0];
    for(var index=0;index<this.length;index++){
        min=(this[index]<min)?this[index]:min;
    }
    
    return min;
};

console.log([3,6,2,4].min());
View Code

這個地方有個坑,當對Array進行擴展後,使用for-in循環會將數組循環出來code

經過代碼demo一下該陷阱(假設已經向Array擴展了min方法):

var arr=[2,4,3,6];
var total=0;

for(var i in arr){
    total+=parseInt(arr[i],10);
}
console.log(total);
View Code

經過demo程序演示一下如何解決該問題:

var arr=[2,4,6,3];
var total=0;

for(var i in arr){
    if(arr.hasOwnProperty(i)){
        total+=parseInt(arr[i],10);
    }
}
console.log(total);
View Code

3.接下來介紹一下什麼是構造器(Constructor): a.constructor始終指向建立當前對象的構造(初始化)函數 b.每一個函數都有一個默認的prototype屬性,而這個prototype屬性的constructor指向該函數

而後經過程序實例demo一下:

///
/// 等價於 var arr=new Array(2,4,6,5);
///
var arr=[2,4,6,5];
console.log(arr.constructor===Array);    //true

///
/// 等價於 var Foo=new Function();
///
var Foo=function(){
};
console.log(Foo.constructor===Function);    //true

var obj=new Foo();
console.log(obj.constructor===Foo);        true


console.log(obj.constructor.constructor===Function);    true
View Code

當constructor遇到prototype時,就會發生一種一下狀況:
有上述能夠知道每一個函數都有默認的屬性prototype,而這個默認的額prototype屬性的constructor指向該函數

function Person(name){
    this.name=name;
};

Person.prototype.getName=function(){
    return this.name;
};

var obj=new Person('test person');

console.log(obj.constructor===Person);        //true
console.log(Person.prototype.constructor===Person);        //true

console.log(obj.construtor.prototype.constructor===Person);        //true
View Code

當咱們從新定義prototype時,就會出現一個很奇怪的現象(如下實例是覆蓋,上述實例是修改),constructor就會有所不一樣

function Person(name){
    this.name=name;
};

Person.prototype={

    getName:function(){
        return this.name;
    }
};

var obj=new Person('test person');

console.log(obj.constructor===Person);        //false
console.log(Person.prototype.constructor===Person);        //false

console.log(obj.construtor.prototype.constructor===Person);        //false
View Code

如下簡單分析一下出現該現象的緣由,覆蓋操做等價於如下代碼:

Person.prototype = new Object({getName:function () {   
    return this.name;   
}}); 
View Code

而constructor始終指向建立自身的函數,所以Person.prototype.constructor===Object
咱們能夠經過從新覆蓋construtor來解決該問題:

function Person(name) {   
    this.name = name;   
};   
Person.prototype = new Object({getName:function () {   
    return this.name;   
}});   
Person.prototype.constructor = Person;   
var obj = new Person("test person");   
console.log(obj.constructor === Person);        // true   
console.log(Person.prototype.constructor === Person);    // true   
console.log(obj.constructor.prototype.constructor === Person);    // true
View Code
相關文章
相關標籤/搜索