1:作用域安全的构造函数
1.1 什么是作用域不安全的构造函数
构造函数就是一个使用new操作符的函数,使用new操作符时,函数内部的this就指向调用构造函数后产生的实例,一旦你调用构造函数没有使用new,构造函数内部的this就将指向window对象,造成更多意想不到的问题。
正常使用:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function Person(name,age,job) 2 { 3 this.name = name; 4 this.age = age; 5 this.job = job; 6 } 7 8 var person = new Person("Tom",29,"SE"); 9 alert(person.name);//Tom 10 alert(person.age);//29 11 alert(person.job);//SE
错误使用:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function Person(name,age,job) 2 { 3 this.name = name; 4 this.age = age; 5 this.job = job; 6 } 7 8 var person = Person("Tom",29,"SE"); 9 alert(window.name);//Tom 10 alert(window.age);//29 11 alert(window.job);//SE 12 alert(person.name);//Error 13 alert(person.age);//Error 14 alert(person.job);//Error
为了防止这种错误调用,可以在构造函数内部判断this的指向来进一步完善构造函数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function Person(name,age,job) 2 { 3 if(this instanceof Person) 4 { 5 this.name = name; 6 this.age = age; 7 this.job = job; 8 } 9 else 10 { 11 return new Person(name,age,job); 12 } 13 } 14 15 var person = Person("Tom",29,"SE"); 16 alert(window.name);//undefined 17 alert(window.age);//undefined 18 alert(window.job);//undefined 19 alert(person.name);//Tom 20 alert(person.age);//29 21 alert(person.job);//SE
使用instanceof确保this指向的是Person的实例,无论如何,最后调用构造函数都会使用new操作符。
1.2 作用域安全的构造函数的继承问题
作用域安全的构造函数实际上锁定了可以调用此构造函数的环境,在使用借用构造函数的方式来继承父类时,如果遇见父类的构造函数是作用域安全的,将会导致继承不到父类。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function Father(name) 2 { 3 if(this instanceof Father) 4 { 5 this.fatherName = name; 6 this.firends = ['alex','tom']; 7 } 8 else 9 { 10 return new Father(name);//将返回一个Father实例 11 } 12 } 13 function Child(name) 14 { 15 Father.call(this,"father1");//这里传入的this指向了Child的实例,获得一个不曾使用的Father实例 16 this.childName = name; 17 } 18 var child1 = new Child("child1"); 19 alert(child1.fatherName);//undefined
问题关键在于this的指向,联系几种继承方式,原型链继承可以改变this的指向,当用原型链方式继承father时,child中this的指向也可以是father了,所以一综合,就是原来的组合继承方式就可以规避这个问题。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function Father(name) 2 { 3 if(this instanceof Father) 4 { 5 this.fatherName = name; 6 this.firends = ['alex','tom']; 7 } 8 else 9 { 10 return new Father(name); 11 } 12 } 13 function Child(name) 14 { 15 Father.call(this,"father1"); 16 this.childName = name; 17 } 18 Child.prototype = new Father("father2");//现在指向Child实例的this也同样指向了Father 19 //father2 被同名属性father1覆盖了 20 var child1 = new Child("child1"); 21 alert(child1.fatherName);//father1
2:惰性载入函数
前端总是要判读很多兼容性问题,比如使用Ajax时要创建的XMLHttpRequest对象,各个浏览器之间创建的方式不尽相同,会用到大量try catch语句,很显然,这个判断过程只需要执行一次就可以了,让函数记忆住成功创建的方式,下次使用就会快很多了。
一般方式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function createRequest() 2 { 3 var HttpRequest = null; 4 try 5 { 6 // For Mazilla or Safari or IE7 7 HttpRequest = new XMLHttpRequest(); 8 } 9 catch (e) 10 { 11 var XMLHTTPS = new Array( "MSXML2.XMLHTTP.5.0", 12 "MSXML2.XMLHTTP.4.0", 13 "MSXML2.XMLHTTP.3.0", 14 "MSXML2.XMLHTTP", 15 "Microsoft.XMLHTTP" ); 16 var Success = false; 17 for (var i = 0; i < XMLHTTPS.length && Success == false; i+=1) 18 { 19 try 20 { 21 HttpRequest = new ActiveXObject(XMLHTTPS[i]); 22 Success = true; 23 } 24 catch (e) { } 25 if (!Success) 26 { 27 this.onError("Browser do not support Ajax."); 28 } 29 } 30 } 31 return HttpRequest; 32 }
惰性载入方式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 function createRequest() 2 { 3 var HttpRequest = null; 4 try 5 { 6 // For Mazilla or Safari or IE7 7 HttpRequest = new XMLHttpRequest(); 8 createRequest = function(){ 9 return XMLHttpRequest(); 10 }; 11 return HttpRequest; 12 } 13 catch (e) 14 { 15 var XMLHTTPS = new Array( "MSXML2.XMLHTTP.5.0", 16 "MSXML2.XMLHTTP.4.0", 17 "MSXML2.XMLHTTP.3.0", 18 "MSXML2.XMLHTTP", 19 "Microsoft.XMLHTTP" ); 20 var Success = false; 21 for (var i = 0; i < XMLHTTPS.length && Success == false; i+=1) 22 { 23 try 24 { 25 HttpRequest = new ActiveXObject(XMLHTTPS[i]); 26 Success = true; 27 createRequest = function(){ 28 return new ActiveXObject(XMLHTTPS[i]); 29 }; 30 return HttpRequest; 31 } 32 catch (e) { } 33 if (!Success) 34 { 35 this.onError("Browser do not support Ajax."); 36 } 37 } 38 } 39 createRequest = function(){ 40 throw new Error("NO XHR object available"); 41 }; 42 return HttpRequest; 43 }