1、三种类型模式javascript
设计模式、编码模式、反模式java
2、JavaScript基本概念设计模式
一、面向对象浏览器
五种基本类型:数字、字符串、布尔、undefine、null缓存
函数也是对象,也有属性和方法安全
对象有两种类型:一、原生的 ECMAScript 二、主机的,在主机环境中定义,如浏览器闭包
原生包括:内置对象和用户自定义对象app
主机包括:window对象和全部DOM对象函数
二、原型工具
原型是个对象,每一个都会自动获取一个Prototypes属性,该属性指向一个新的空对象
三、JSLint
javascript是一门解析语言没有静态编译时检查,JSLint是检查JavaScript代码质量的工具
本章讨论一些高质量代码的核心方法、模式和习惯,如避免全局变量、使用单个变量var的声明、循环中缓存长度变量length和符合代码的约定.
1、编写可维护代码
一、减小全局变量
全局对象能够在函数外部使用this访问
mylobal = "hello"; // 全局变量
console.log(mylobal);
console.log(window.mylobal);
console.log(window["mylobal"]);
全局变量的问题:一、第三方Javascript库 二、广告合做伙伴的脚本
释放变量:使用var 建立的变量不能删除,不使用var建立的隐含全局变量能够删除,隐含变量不是真正的变量,而是全局对象的属性,能够经过delete删除
// 定义三个全局变量
var global_var = 1;
global_noar = 2;
(function(){
global_fromfunc = 3;
})
delete global_var; // false
delete global_noar; // true
delete global_fromfunc; // true
二、单一的var模式
用一个var在函数顶部进行变量的声明
var a = 0,
b = 1;
三、for循环
当遍历时存储长度,
var oLi = document.getElementsByTagName("li");
for(var i=0, len=oLi.length; i< len; i++){ ... }
四、不在增长内置的原型
就是别在内置的构造函数内增长新功能,
五、switch模式
提升switch的可读性和健壮性
var inspect = 0, result = "";
swith(inspect){
case 0:
result = "zero"; break;
case 1:
result = "one"; break;
default:
retult = "unknown";
}
若是不写break语句会接着向下执行
6 、parseInt()的数值约定
parseInt()从一个字符串中获取数值,第二个参数为进制,但若是字符串为0开头就必须写进制,如"08",parseInt("08", 10);不然在ie下会输出
另外一种写法能够:
+"08"; 或者 Number("08")
1、对象字面量
// 定义一个空对象
var dog = {};
// 向对象加一个属性和方法
dog.name = "benji";
dog.getName = function(){
return dog.name;
}
2、构造函灵敏
1 var Person = function(name){ 2 this.name = name; 3 this.say = function(){ 4 return this.name; 5 } 6 }
构造函数原型prototyp的做用
将say方法添加到this中,若是在任什么时候间调用new Person()时都会在内存中建立一个新的函数,会使效率低下,由于建立多个person实例时也会建立多个say方法,解决方法是将他们添加到原型中prototype
函数的两个特色:一、函数是一类对象 二、函数能够提供一个做用域
一、全局做用域:function foo(){}
二、局部做用域:
function local(){
// 局部做用域
function bar(){};
return bar;
}
三、函数表达式 var bar = function(){ ... }
四、匿名函数 function(){ ... }; 没有名称,在自动函数或赋给一个变量时使用
五、即时执行函数 (function(){ ... })();
即时函数的参数:
(function(who, when){
console.log("i met" + who);
})("joe black", new Date())
即时函数的返回值:
var result = (function(){
return 2 + 3;
})();
1、命名空间模式
命名空间有助于减小全局变量的数量,而且避免合名冲突或过长的名字前缀
1 <script> 2 // 不安全代码,好比两个js文件中都有这会MYAPP的建立,这样第二个会覆盖掉第一个对象 3 var MYAPP = {}; 4 5 // 更好的代码风格 6 if(typeof MYAPP === "undefined"){ 7 var MYAPP = {}; 8 } 9 10 // 或者使用 11 var MYAPP = MYAPP || {}; 12 </script>
检测代码须要太多的重复工做,若是想定义MYAPP.modeles.module就必须三次检查,每次都须要检查一次对象或属性,可使用namespace()函数
1 <script> 2 MYAPP.namespace("MYAPP.modules.getName"); 3 4 // 至关于 5 MYAPP.modules.getName = {} 6 7 8 // 定义一个命名空间函数 9 var MYAPP = MYAPP || {}; 10 MYAPP.namespace = function(sName, newObj){ 11 var parts = sName.split("."), 12 argLen = arguments.length, 13 parent = MYAPP; 14 15 // 剥离最前面的全局变量 16 if(parts[0] == "MYAPP"){ 17 parts = parts.slice(1); 18 } 19 20 if(argLen == 2 && (typeof newObj === "object" || typeof newObj === "function")){ 21 for(var i= 0,len = parts.length; i<len; i++){ 22 if(i == len-1){ 23 parent[parts[i]] = $.extend(newObj, parent[parts[i]]); // 须要继承以前的对象 24 } 25 else{ 26 // 若是不存在就建立一个新的属性 27 if(typeof parent[parts[i]] === "undefined"){ 28 parent[parts[i]] = {}; 29 } 30 } 31 parent = parent[parts[i]]; 32 } 33 } 34 else{ 35 for(var i= 0,len = parts.length; i<len; i++){ 36 // 若是不存在就建立一个新的属性 37 if(typeof parent[parts[i]] === "undefined"){ 38 parent[parts[i]] = {}; 39 } 40 parent = parent[parts[i]]; 41 } 42 } 43 44 return parent; 45 } 46 47 // 一、建立一个命名空间,并初始化命名空间的对象 48 var ssq = MYAPP.namespace("MYAPP.storage.getStorage", { 49 50 init: function(){ 51 this.bindEvent(); 52 }, 53 54 bindEvent: function(){ 55 console.log("bind All"); 56 } 57 58 }); 59 60 // 调用 61 ssq.init(); // 结果 bind All 62 63 // 二、建立一个命名空间,初始化时为函数,其实使用对象也彻底能够作到,MYAPP.namespace("MYAPP.storage", {showFun: function(){ console.log("匿名函数"); }}; 64 var dlt = MYAPP.namespace("MYAPP.storage.showFun", function(){ 65 console.log("匿名函数"); 66 }); 67 68 // 调用 69 dlt(); 70 </script>
2、私有属性、方法
js中没有私有成员的语法,能够经过闭包,或内部变量来实现这种功能。
1 <script> 2 function Gadget(){ 3 4 // 私有成员 5 var name = "iPad"; 6 7 // 公有函数 8 this.getName = function(){ 9 return name; 10 } 11 } 12 13 var toy = new Gadget(); 14 console.log(toy.name); // undefined 15 console.log(toy.getName()); // iPad 16 </script>
3、特权方法
就是经过公有方法来访问私有属性,这个方法能够叫作特权方法,上面的例子getName()就是个特权方法.
4、模块模式
1 <script> 2 var myObj = (function(){ 3 4 // 私有成员 5 var name = "my, oh my"; 6 7 // 实现公有部分 8 return { 9 getName: function(){ 10 return name; 11 } 12 } 13 })(); 14 </script>
一、构造函数的模块
1 <script> 2 var MYAPP = MYAPP || {}; 3 4 // 命名空间函数 5 MYAPP.namespace = function(sName, newObj){ 6 var parts = sName.split("."), 7 argLen = arguments.length, 8 parent = MYAPP; 9 10 // 剥离最前面的全局变量 11 if(parts[0] == "MYAPP"){ 12 parts = parts.slice(1); 13 } 14 15 if(argLen == 2 && (typeof newObj === "object" || typeof newObj === "function")){ 16 for(var i= 0,len = parts.length; i<len; i++){ 17 if(i == len-1){ 18 parent[parts[i]] = $.extend(newObj, parent[parts[i]]); // 须要继承以前的对象 19 } 20 else{ 21 // 若是不存在就建立一个新的属性 22 if(typeof parent[parts[i]] === "undefined"){ 23 parent[parts[i]] = {}; 24 } 25 } 26 parent = parent[parts[i]]; 27 } 28 } 29 else{ 30 for(var i= 0,len = parts.length; i<len; i++){ 31 // 若是不存在就建立一个新的属性 32 if(typeof parent[parts[i]] === "undefined"){ 33 parent[parts[i]] = {}; 34 } 35 parent = parent[parts[i]]; 36 } 37 } 38 39 return parent; 40 } 41 42 MYAPP.namespace("MYAPP.util"); // 建立一个命名空间 43 MYAPP.util = (function(){ 44 45 // 依赖 46 var oLib = MYAPP.lib; 47 48 // 建立构造函数 49 function Constr(){ 50 this.elements = "siguang"; 51 } 52 53 Constr.prototype.version = "2.0"; 54 Constr.prototype.showMessage = function(){ 55 console.log(this.version, this.elements); 56 } 57 58 var oConstr = new Constr(); 59 60 return oConstr; 61 }()); 62 63 console.log(MYAPP); 64 65 // 调用 66 MYAPP.util.showMessage(); // 67 </script>
二、将全局变量导入到模块中
1 <script> 2 MYAPP.utilities.module = (function(app, global){ 3 // 引用全局对象 4 // 能够转成局部变量 5 // 全局应用程序命名空间对象 6 })(MYAPP, this) 7 </script>
1、包装对象
什么是包装对象
var str = "ssssssss";
str.charAt(3);
str.substring(2);
通常方法是调用的是对象,而str是字符串,这就是用到了包装对象,基本类型都有本身的包装对象
例如:字符串包装类型是String 数字是Number 布尔是Boolean,为何str能够调用字符串的方法,看下面的例子
1 <script> 2 var str = new String("haha"); // 将字符串到String对象 3 4 // String的对象的方法 5 String.prototype.charAt = function(n){ 6 // .... 7 } 8 </script>
var str = "haha"; // 这句正常定义变量
str.charAt(2); // 这里基本类型str会找到对应包装对象的方法,将属性及方法赋给基本类型,而后包装对象消失
1、类式继承
类式继承的几种写法:
一、默认模式
1 <script> 2 3 // 父构造函数 4 function Parent(name){ 5 this.name = name || "siguang"; 6 this.age = "30"; 7 this.setGame = function(){ 8 console.log(this.age); 9 } 10 } 11 12 // 向该原型添加功能 13 Parent.prototype.say = function(){ 14 return this.name; 15 } 16 17 // 空构造函数 18 function Child(name, age){ 19 this.age = age; 20 Parent.call(this, name); // 改变父类的属性,不然调用的就是父类的属性 21 } 22 23 // 继承方法,封装了一个 24 inherit(Child, Parent); 25 26 function inherit(C, P){ 27 C.prototype = new P(); // 继承方法 28 } 29 30 var oC = new Child("lulu", 28); 31 console.log(oC.say()); // lulu 32 oC.setGame(); // 30 33 </script>
类式继承继承父类的属性和方法,若是改变其属性须要将改变指针Parent.call(this, name);
此模式的缺点:同时继承两个对象的属性,将子类传入age时this.age = age 输出的并非预期的28而仍是父类的30,这也就是第二种模式
二、共享原型
修改了inherit方法
function inherit(C, P){
C.prototype = P.prototype; // 缺点:在继承链的某一个子对象或孙对象修改了原型,会影响到父对象和祖先对象.
}
三、临时构造函数