个人随笔
目录
JS实现作用域安全的构造函数
2020-05-21 23:16:10
摘要:JS、JS构造函数、作用域安全的构造函数

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

  1. function Person(name, age, job){
  2. this.name = name;
  3. this.age = age;
  4. this.job = job;
  5. }
  6. var person = new Person("Nicholas", 29, "Software Engineer");

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

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

如果此时直接person.age将会报错,因为没有new关键字所以this没有映射到对象person上。

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

  1. function Person(name, age, job){
  2. if (this instanceof Person){
  3. this.name = name;
  4. this.age = age;
  5. this.job = job;
  6. } else {
  7. return new Person(name, age, job);
  8. }
  9. }
  10. var person1 = Person("Nicholas", 29, "Software Engineer");
  11. alert(window.name); //""
  12. alert(person1.name); //"Nicholas"
  13. var person2 = new Person("Shelby", 34, "Ergonomist");
  14. alert(person2.name); //"Shelby"

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

 335

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2