• 深入理解Javascript中this, prototype, constructor


    在Javascript面向对象编程中经常需要使用到this,prototype和constructor这3个关键字.

    1.首先介绍一下this的使用:this表示当前对象;如果在全局中使用this,则this为当前页面对象window;如果在函数中使用this,则this为调用该函数的对象;可以使用apply和call两个全局函数来改变this的指向。

    接下来,首先通过几个demo程序验证一下:

    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的指向:

    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):

    prototype本质上还是Javascript的一个对象;每个函数都有一个默认的prototype属性;通过prototype可以扩展Javascript中的内建对象。

    接下来通过Demo展示一下如何使用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内建对象:

    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循环会将数组循环出来

    通过代码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
  • 相关阅读:
    global s power in php...
    null is empty
    如何创建spring web 工程
    如何下载spring sts
    使用apache-commons-lang3架构对HTML内容进行编码和反编码
    SQL 查询建表SQL
    kindeditor 在JSP 中上传文件的配置
    在java web工程中jsp页面中使用kindeditor
    实现<base>标签中有绝对路径
    实现多个JSP页面共用一个菜单
  • 原文地址:https://www.cnblogs.com/chengbing2011/p/4202944.html
Copyright © 2020-2023  润新知