JavaScript_高级应用初探之——作用域安全的构造函数

  在实际的JavaScript代码设计的过程中,难免会用到构造函数,使用构造函数意义在于能够使我们设计的对象实现多次复制和初始化。但在有时候,构造函数也会存在一些问题。如下面的例子:

function Perso(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
}

var person = new Person("jix", "24", "software engineer");

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

var person  = Person("jix", 24, "Software Engineer");
console.log(person.name);//"无法获取属性“name”的值: 对象为 null 或未定义" 

我们自这里执行了“var person = Person("jix", 24, "Software Engineer");”这一句,却是将Person作为一个一般函数执行了。于是出现了两个问题:

  1. 当Person作为一个普通function调用时,它并没有返回值,于是person也就只能是一个未初始化的变量了,当我们向未初始化的person变量取其name属性值是,必然会报一个"无法获取属性“name”的值: 对象为 null 或未定义"的错;
  2. 由于this映射到了window对象上,所以我们的name属性也就相应的添加到了window对象。

问题并没有就此结束,由于window的name属性是用于识别连接目标和框架的,所以这里对该属性的偶然覆盖可能会导致该页面上出现其他错误。于是,需求被提出来了,我们需要一个作用域安全的构造函数。

  作用域安全的构造函数在进行任何更改前,首先确认this对象时正确类型的实例。如果不是,那么会创建新的实例并返回。

function Person(name, age, job){
    if(this instanceof Peson){
        this.name  =  name;
        this.age = age;
        this.job = job;
    }else
        return new Person(name, age, job);
}

var person1 = Person("jix", 24, "Software Engineer");
console.log(person1.name);//jix

var person2 = new Person("body", 25, "Brunch");

console.log(person2.age);//body

  上面这段代码中的Person构造函数提供了一个检查this对象是否是Person实例的if语句,保证了在任何情况下,对象初始化都能正常进行。

注释:当然,在我们实现了上面这个模式后,你就所订立可以调用构造函数的韩靖如果你使用构造函数窃取模式的继承且不使用原型链,那么这个继承很可能被破坏。原因和解决方法下一次写。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2013-03-17 19:20  鸡血小青年  阅读(168)  评论(0)    收藏  举报

导航