• [转]JavaScript作用域安全构造函数


          构造函数其实就是一个使用new操作符调用的函数。当使用new调用时,构造函数内用到的this对象会对指向新创建的对象实例,如下的例子所示:

    function Person(name, age, job){    
        this.name = name;    
        this.age = age;    
        this.job = job;
    }
    var person =("Nicholas",29,"Software Engineer");

          上面这个例子中,Person构造函数使用this对象给三个属性赋值:name、age和job。当和new操作符连用时,则会创建一个新的Person对象,同事会给它分配这些属性。问题在当没有使用new操作符来调用构造函数的情况时。由于该this对象是在运行时绑定的,所以直接调用Person(),this会映射到全局对象window上,导致错误对象属性的意外增加。例如:

    var person =Person("Nicholas",29,"Software Engineer");
    alert(window.name);//"Nicholas"
    alert(window.age);//29
    alert(window.job);//"Software Engineer"

          这里,原本针对Person实例的三个属性被加到window对象上,因为构造函数是作为普通函数调用的,忽略了new操作符。这个问题是由this对象的晚绑定造成的,在这里this呗解析成了window对象。由于window的name属性是用于识别链接目标和框架的,所以这里对该属性的偶然覆盖可能会导致该页面上出现其它错误。这个问题的解决方法就是创建一个作用域安全的构造函数。
    作用域安全的构造函数在进行任何更改前,首先确认this对象是正确类型的实例。如果不是,那么会创建新的实例并返回。请看下面的例子:

    function Person(name, age, job){
        if(this instanceof Person){        
            this.name = name;        
            this.age = age;        
            this.job = job;    
        }else{        
            return new Person(name, age, job);
        }
    }
    var person1 =Person("Nicholas",29,"Software Engineer");
    alert(window.name);//""
    alert(person1.name);//"Nicholas"
    var person2 =new Person("Shelby",34,"Ergonomist");
    alert(person2.name);//"Shelby"

          这段代码中的Person构造函数添加了一个检查并确保this对象是Person实例的if语句,它表示要么使用new操作符,要么在现有的Person实例环境中调用构造函数。任何一种情况下,对象初始化都能正常进行。如果this并非Person实例环境中调用构造函数。任何一种情况下,对象初始化都能正常进行。如果this并非Person的实例,那么会再次使用new操作符调用构造函数并返回结果。最后的结果是,调用Person构造函数时无论是否使用new操作符,都会返回一个Person的新实例,这就避免了在全局对象上意外设置属性。

  • 相关阅读:
    天大复试机试练习_003
    C++随手记--字符串转数字
    C++标准库STL 之 我觉得应该有的方法——split
    apt-get 详解&&配置阿里源
    Nginx 图文详解
    MySQL数据库管理常用命令小结
    oracle数据库备份
    SqlServer数据库备份还原步骤
    mysql数据备份与恢复
    Tomcat架构
  • 原文地址:https://www.cnblogs.com/iRavior/p/3409654.html
Copyright © 2020-2023  润新知