1、註釋寫法javascript
1 /* 2 * @author: 做者 3 * @action: 組件的做用 4 * @date: 建立日期 5 * 6 * Options : events delay // 屬性 7 * Methods : currentShow getContent // 方法 8 * Events : beforeClick afterClick // 自定義事件或系統事件 9 */
1、面向對象的一些重要的方面css
一、對象引用 二、做用域 三、閉包 四、上下文java
引用:引用就是指向對象實際位置的指針,多個變量能夠引用一個對象程序員
1 <script> 2 var obj = new Object(); // 建立一個新類 3 var objRef = obj; // 將引用地址賦給這個變量 4 obj.one = true; // 建立類的屬性 5 alert(obj.one === objRef.one); // 返回true 6 </script>
做用域:是JS中一個難處理的特性,在JS裏做用域由函數所約束,而不禁塊約束(如for,if,while語句)編程
1 <script> 2 // 例1: 3 var foo = "test"; 4 if(true){ 5 var foo = "new test"; // 這裏仍然是全局變量 6 } 7 alert(foo === "new test"); // 因此返回true 8 9 // 例2: 10 var foos = "test"; 11 function test(){ 12 var foos = "new test"; // 這裏是局布變量 13 } 14 alert(foos === "new test"); // 因此爲false 15 </script>
全局變量都是window的屬性,定義的函數都是window的方法.設計模式
隱式全局變量:閉包
1 <script> 2 var foos = "test"; 3 function test(){ 4 name = "new test"; // 在函數裏沒有用var定義的變量都爲全局變量 5 } 6 alert(name === "new test"); // 返回true 7 </script>
閉包:內層函數能夠引用存在於包繞它的函數變量 async
上下文:是經過變量this工做ide
1 <script> 2 var obj = { 3 yes: function(){ 4 this.val = true; 5 }, 6 no : function(){ 7 this.val = false; 8 } 9 } 10 // 若是直接調用obj.val 對象obj沒有這個屬性因此爲null 11 // 將運行yes方法後this會指向obj上,這時能夠調用obj.val 12 obj.yes(); 13 alert(obj.val); // 返回true 14 </script>
改變上下文模塊化
1 <script> 2 function changeColor(colors) { 3 console.log(this); 4 this.style.color = colors; 5 } 6 // 在window對象上調用這個函數,由於window沒有style對象 7 // new changeColor("white"); 8 9 // 經過call來改變this指針的指向 10 var box = document.getElementById("box"); 11 changeColor.call(box, "red"); 12 </script>
2、面向對象的基礎
一、建立對象和對象屬性方法的兩個例子
1 <script> 2 // 方法一 3 var obj = new Object(); 4 // 建立對象公用屬性和方法 5 obj.name = "哈哈"; 6 obj.sayName = function(){ 7 alert(this.name); 8 } 9 obj.sayName(); 10 11 // 方法二 12 var obj = { 13 name : "哈哈", 14 sayName : function(){ 15 alert(this.name); 16 } 17 } 18 obj.sayName(); 19 </script>
二、公有屬性和方法、私有屬性和方法
1 <script> 2 // 公有屬性、方法 3 function User(name, age){ 4 this.name = name; // 公有屬性 5 this.age = age; 6 } 7 User.prototype.getName = function(){ // 公有方法,經過prototype對象 8 return this.name; 9 } 10 User.prototype.getAge = function(){ 11 return this.age; 12 } 13 var user = new User("哈哈", 30); 14 alert(user.getName() == "哈哈"); // 返回true; 15 16 // 私有屬性、方法 17 function Class(student, teacher){ 18 this.student = student; 19 this.teacher = teacher; 20 var current = 0; // 私有屬性 21 22 function getCurrent(){ 23 return current; 24 } 25 } 26 Class.prototype.getName = function(){ 27 // console.log(current); // 報錯,current爲私有屬性的,返回undefined 28 return this.student; 29 } 30 var className = new Class("aaa", "bbb"); 31 className.getName(); 32 // className.getCurrent(); // 報錯,私有方法不能被外界所訪問 33 </script>
三、特權方法:是用來訪問和改變私有變量的方法
1 <script> 2 function User(name, age){ 3 this.name = name; 4 this.age = age; 5 var year = 2013; 6 this.getYear = function(){ // 特權方法,不能放到prototype中,由於做用域會找不到year 7 return year; 8 } 9 } 10 var user = new User("哈哈", 30); 11 alert(user.getYear()); // 返回2013; 12 </script>
3、命名空間
1 <script> 2 // 建立一個全局的命名空間 3 var YAHOO = {}; 4 5 // 設置一個子的命名空間 6 YAHOO.util = {}; 7 8 YAHOO.util.Event = { 9 addEventListener:function(){ } 10 } 11 12 // 調用方法 13 YAHOO.util.event.addEventListener(); 14 </script>
3、!=、== vs !==、===
在javascript裏,null、0、""、false和undefined所有彼此相等(==),由於他們計算的值都爲false;
1 <script> 2 console.log(typeof null); // 返回Object 3 console.log(typeof undefined); // 返回undefined 4 5 // 常見問題 6 console.log(null == undefined); // false; 7 console.log("" == undefined); // false; 8 console.log(0 == undefined); // true; 9 console.log(String == undefined); // false; 10 console.log(String == null); // false; 11 console.log(String === Object); // false; 12 </script>
1、在編程時你能夠寫採用函數式編程風格,也能夠寫成複雜一點的面象對象編程風格
2、鏈式調用
如jQuery採用的就是鏈式調用,$("#name").find("<p>").addClass("active");
1 <div class="box" id="box">14077期任選9場中頭獎3894注</div> 2 <input type="button" value="添加" id="add"> 3 <input type="button" value="刪除" id="del"> 4 5 <script> 6 function getId(id){ 7 return document.getElementById(id); 8 } 9 10 var oAdd = getId("add"); 11 var oDel = getId("del"); 12 13 function Chain(oId){ 14 this.box = getId(oId); 15 } 16 17 Chain.prototype = { 18 19 // 添加class值 20 addClass: function(claName){ 21 console.log(this.box); 22 var sClass = this.box.getAttribute("class"); 23 this.box.className = sClass+ " " +claName; 24 return this; 25 }, 26 27 // 刪除class值 28 removeClass: function(claName){ 29 var sClass = this.box.getAttribute("class"); 30 var delClass = sClass.replace(/"claName"/, ""); 31 this.box.className = delClass; 32 return this; 33 }, 34 35 // css讀寫樣式 36 css: function(pro, val){ 37 var t = this; 38 if(arguments.length == 1){ 39 console.log("參1") 40 var cssValue = t.getStyle(this.box, pro); 41 return cssValue; 42 } 43 if(arguments.length == 2){ 44 console.log("參2"); 45 t.box.style[pro] = val + "px"; 46 } 47 return this; 48 }, 49 50 // 獲取樣式 51 getStyle: function(obj, attr){ 52 if(obj.currentStyle){ 53 return obj.currentStyle[attr]; 54 } 55 else{ 56 return getComputedStyle(obj, false)[attr] 57 } 58 } 59 60 61 } 62 63 window.$ = function(id){ 64 return new Chain(id); 65 } 66 67 oAdd.onclick = function(){ 68 var getWidth = $("box").addClass("active").css("width"); 69 console.log(getWidth); 70 } 71 72 oDel.onclick = function(){ 73 $("box").addClass("show").removeClass("active").css("width", "20"); 74 } 75 </script>
3、活動的方法
1 1、直接定義函數 2 function start(){ } 3 function end(){ } 4 5 2、建立一個類 6 function Amm(){ } 7 8 Amm.prototype.start = function(){ } 9 Amm.prototype.end = function(){ } 10 11 12 3、傳統的程序員更喜歡把他們寫到一塊兒 13 function Amm(){ } 14 15 Amm.prototype = { 16 start: function(){ }, 17 end: function(){ } 18 } 19 20 4、鏈式調用 21 window.$ = function(id){ 22 return new _$(id); 23 } 24 function _$(id){ 25 this.elements = document.getElementById(id); 26 } 27 _$.prototype = { 28 constructor:_$, 29 hide:function(){ 30 console.log('hide'); 31 return this; 32 }, 33 show:function(){ 34 console.log('show'); 35 return this; 36 }, 37 getName:function(callback){ 38 if(callback){ 39 callback.call(this, this.name); 40 } 41 return this; 42 }, 43 setName:function(name){ 44 this.name = name; 45 return this; 46 } 47 } 48 49 $("box").setName("aa").getName(function(name){ 50 console.log(name); 51 }).hide().show();
4、弱類型語言
在js中變量不用聲明其類型,不帶表變量沒有類型,而是變量類型取決於數據的類型,javascript的類型:整型、字符串、布爾,undefined、null
5、函數是一等對象
函數能夠存儲在變量中,也能夠做爲參數傳給另外一個函數,能夠做爲返回值從其它函數傳出,還能夠進行構造,
匿名函數,沒有名字的函數,自動執行,也能夠賦給一個變量
1 // 匿名函數 2 (function(){ 3 var foo = 20; 4 var bar = 10; 5 alert(foo * bar); 6 })(); 7 8 // 可加參數 9 (function(foo, bar){ 10 alert(foo * bar); 11 })(20, 10); 12 14 // 賦給一個變量 15 var sun = (function(foo, bar){ 16 return foo * bar 17 })(20, 10); 18 alert(sun);
匿名函數最有趣的用途是建立「閉包」,閉包是一個受保護變量的空間,若是一個函數調變量並不想讓這個變量爲全局,也不是局部變量,而且讓變量一直保一直保存,不會隨着函數的結束而自動消毀,這樣就可使用閉包。
6、繼承
繼承中不像其它面象對象語言中那麼簡單,js是使用基於對象的(原型式)繼承
7、Javascript中使用設計模式的緣由?
一、可維護性:下降模塊之間的耦合度,使代碼進行重構和換用不一樣的模塊變得容易
二、溝通:
三、性能:某些模式是起優化做用的能夠提升運行速度,減小傳送到客戶端的代碼量,
8、檢測對象的屬性和方法
一、hasOwnProperty:判斷是不是對象的屬性
var obj = {}; obj.name = "haha"; obj.hasOwnProperty("haha"); // 返回true
二、constructor:查看對象是不是構造函數
1 var type = function(o){ 2 return (o === null) ? "null" : typeof o; 3 } 4 5 var arr = new Array(); 6 7 if(type.constructor == Function){ 8 console.log("function"); 9 } 10 11 if(arr.constructor == Array){ 12 console.log("array"); 13 }
三、instanceof:查看對象與構造函數之間的關係,若是對象繼承過其餘構造函數的方法,那就也返回真
var arr = []; alert(arr instanceof Array); alert(arr instanceof Object); // 都返回true
1、什麼是接口
接口提供一種說明一個對象中的哪些方法
接口的好處:能促進代碼的重用,接口能夠告訴程序員一個類實現了哪些方法
爲對象建立私有成員是面向對象的特性之一,目前有幾種方法來建立私有、公有、特權方法的對象
封裝:經過將一個方法或者屬性聲明爲私用的,可讓對象的實現細節對其餘對象保密以下降對象之間的耦合程度,能夠保持數據的完整性並對其修改方式加以約束,這樣能夠是代碼更可靠,更易於調試。封裝是面向對象的設計的基石。
儘管JavaScript是一門面向對象的語言,可它並不具有將成員聲明爲公用或私用的任何內部機制,因此咱們只能本身想辦法實現這種特性。下面仍是經過一套完整的代碼去分析,介紹什麼是私有屬性和方法,什麼是特權屬性和方法,什麼是公有屬性和方法,什麼是公有靜態屬性和方法。
私有屬性和方法:函數有做用域,在函數內用var 關鍵字聲明的變量在外部沒法訪問,私有屬性和方法本質就是你但願在對象外部沒法訪問的變量。
特權屬性和方法:建立屬性和方法時使用的this關鍵字,由於這些方法定義在構造器的做用域中,因此它們能夠訪問到私有屬性和方法;只有那些須要直接訪問私有成員的方法才應該被設計爲特權方法。
1 function SetObject(name, age, sex){ 2 var _name = name; 3 var _age = age; 4 var _sex = sex; 5 6 this.writeInfo = function(){ 7 console.log("name:" + _.name + " age:" + _.age + " sex:" + _.sex); 8 } 9 } 10 11 SetObject.prototype = { 12 setInfo: function(){ 13 this.writeInfo(); 14 } 15 } 16 17 var createObj = new SetObject("jack", 20, "男"); 18 createObj.setInfo();
共有屬性和方法:直接鏈在prototype上的屬性和方法,不能夠訪問構造器內的私有成員,能夠訪問特權成員,子類會繼承全部的共有方法。
共有靜態屬性和方法:最好的理解方式就是把它想象成一個命名空間,實際上至關於把構造器做爲命名空間來使用。
1 /* -- 封裝 -- */ 2 var _packaging =function(){ 3 //私有屬性和方法 4 var name ='Darren'; 5 var method1 =function(){ 6 //... 7 } 8 9 //特權屬性和方法 10 this.title ='JavaScript Design Patterns' ; 11 this.getName =function(){ 12 return name; 13 } 14 } 15 16 //共有靜態屬性和方法 17 _packaging._name ='Darren code'; 18 _packaging.alertName =function(){ 19 alert(_packaging._name); 20 } 21 22 //共有屬性和方法 23 _packaging.prototype = { 24 init:function(){ 25 //... 26 } 27 }
繼承通常是在一個基礎類上又增長了新的功能,但不想破壞這個基礎類中的方法和屬性,這樣能夠建立一個新的超類將基礎類繼承過來
繼承分爲兩種繼承:一、繼承屬性 使用call來繼承父類的屬性 二、繼承方法,使用for...in的方式將父類的方法繼承過來
一、只繼承屬性:
1 // 構造模式 2 function TabB(name, age){ 3 this.name = name; 4 this.age = age; 5 } 6 TabB.prototype = { 7 sayName : function(){ 8 alert(this.name); 9 }, 10 showAge : function(){ 11 alert(this.age) 12 } 13 } 14 15 // 建立繼承類 16 function CopyTabB(name, age, show){ 17 TabB.call(this, name, age); 18 this.show = show; 19 } 20 21 CopyTabB.prototype = { 22 childerName : function(){ 23 console.log(this.name); 24 } 25 } 26 27 var newTagB = new CopyTabB("虎虎", 20, true); 28 newTagB.childerName(); 29 // newTagB.sayName(); // 由於沒有繼承父類的方法因此就會報錯
二、只繼承方法:有兩種方式
第一種方式:CopyTabB.prototype = new TabB(); // 將子類的原型 = 建立的父類
1 function TabB(name, age){ // 建立父類 2 this.name = name; 3 this.age = age; 4 } 5 TabB.prototype = { 6 sayName : function(){ 7 alert(this.name); 8 } 9 } 10 11 // 建立繼承的子類 12 function CopyTabB(name, age, show){ 13 TabB.call(this, name, age); 14 this.show = show; 15 } 16 CopyTabB.prototype = TabB.prototype; 17 // CopyTabB.prototype = new TabB(); 這兩種方法都是繼承方法不繼承屬性 18 19 var newTagB = new CopyTabB("虎虎", 20, true); 20 newTagB.sayName();
第二種方式:for...in將對象的方法循環出來
1 // 構造模式 2 function TabB(name, age){ 3 this.name = name; 4 this.age = age; 5 } 6 TabB.prototype = { 7 sayName : function(){ 8 alert(this.name); 9 }, 10 showAge : function(){ 11 alert(this.age) 12 } 13 } 14 15 // 建立繼承類 16 function CopyTabB(name, age, show){ 17 TabB.call(this, name, age); 18 this.show = show; 19 } 20 21 extend(TabB.prototype, CopyTabB.prototype); // 將父親類的全部方法賦給子類 22 23 // 將父類的方法賦給子類 24 function extend(oParent, oChilder){ 25 for(var attr in oParent){ 26 oChilder[attr] = oParent[attr]; 27 } 28 } 29 30 var newTagB = new CopyTabB("虎虎", 20, true); 31 newTagB.sayName();
-----------------------------------------------------------------------------------------------
繼承是一個抽象的話題,繼承有兩種方式:一、類繼承 二、原型繼承
一、prototype繼承
1 // 定義一個超類 2 function PeopleA(name){ 3 this.name = name; 4 } 5 6 // 給超類添加一個方法 7 PeopleA.prototype.getName = function(){ 8 return this.name; 9 } 10 11 12 // 在定義一個超類 13 function PeopleB(name, sex){ 14 PeopleA.call(this, name); 15 this.sex = sex; 16 } 17 18 // 類繼承 19 PeopleB.prototype = new PeopleA(); // 將new一個對象賦給prototype 20 // PeopleB.prototype = PeopleA.prototype; // 也能夠這樣寫 21 22 /* 23 * 注:必定要將B類的方法寫在,類繼承以後,由於方法中還有調A中的屬性 24 * */ 25 // 給B超類添加一個方法 26 PeopleB.prototype.writeInfo = function(){ 27 return this.name + this.sex; 28 } 29 30 // 實例化話PeopleB類 31 var createPeopleB = new PeopleB("全家", 20); 32 // console.log(createPeopleB.getName()); // 若是不繼承就不能使用PeopleA中的方法 33 console.log(createPeopleB.getName()); 34 console.log(createPeopleB.writeInfo());
二、原型繼承
1 <script> 2 // 建立一個超類 3 function Person(name){ 4 this.name = name; 5 } 6 Person.prototype.getName = function(){ 7 return this.name; 8 } 9 10 // 建立一個新類 11 function User(name, passwrod){ 12 Person.call(this, name); 13 this.passwrod = passwrod; 14 }
15 User.prototype = new Person() // User對象繼承Person的全部方法
// User.prototype = Person.prototype;
16 User.prototype.getPasswrod = function(){ 17 return this.password; 18 } 19 20 var person = new User("names", 1111); 21 alert(person.getName()); 22 </script>
屬性和方法均可以繼承
1 function Obj1(){ // 建立一個對象 2 this.name = "siguang"; 3 } 4 Obj1.prototype.sayName = function(){ 5 return this.name; 6 } 7 8 function Obj2(){ // 另外一個對象 9 this.age = 20; 10 } 11 12 Obj2.prototype = new Obj1(); 13 14 var newObj = new Obj2(); 15 var sName = newObj.sayName(); 16 console.log(newObj.name); // siguang 17 console.log(sName); // siguang
1、單例模式
模塊模式是爲單例模式建立私有變量和特權方法,所謂的單例模式,指的就是隻有一個實例的對象,javascript是以對象字面量來建立單例模式
單例模式的用途:提供一個建立一系列相關或相互依賴對象的接口,而無需指定他們具體的類。
工廠就是把成員對象的建立工做轉交給一個外部對象,好處在於消除對象之間的耦合(何爲耦合?就是相互影響)。經過使用工廠方法而不是new關鍵字及具體類,能夠把全部實例化的代碼都集中在一個位置,有助於建立模塊化的代碼,這纔是工廠模式的目的和優點。
一、普通的對象字面量單例:都是公有的屬性和方法
1 var obj = { 2 name : "My Object", 3 getNameFun : function(){ 4 alert(this.name); 5 } 6 } 7 obj.getNameFun()
二、單例模式,聲明的私有變量和方法
1 var singleton = function(){ 2 // 私有變量和私有函數 3 var privateVar = 10; 4 5 // 私有函數 6 function privateFun(){ 7 return false; 8 } 9 10 // 返回對象,能夠經過特權方法來訪問私有屬性和私有方法 11 return { 12 publicVar : 10, 13 publicMethod : function(){ 14 privateVar++; 15 } 16 } 17 } 18 19 singleton.publicMethod();
單體模式之利:把方法和屬性組織在一個不會被屢次實例化的單體中,描述性的命名空間能夠加強代碼的自我說明
單體模式之弊:單體模式提供單點訪問,致使模塊之間的藕和性
2、原型模式(構造函數)
經過每一個函數,都有一個prototype的屬性來創造其原型方法,全部建立的對象只有一套prototype原型的方法或屬性
1 function GetObj(name, old){ 2 this.name = name; 3 this.old = old 4 } 5 6 GetObj.prototype = { 7 init : function(){ 8 alert(this.name + "," + this.old); 9 } 10 } 11 12 var obj = new GetObj("aa", "bb"); 13 obj.init();
普通函數與構造函數的區別
function show(){ // var this = new object(); // 若是是new出來的會自動建立一個 alert(this); } show(); // 這個時候this指向window new show(); // 時候this指向object,若是用new出來的函數系統會自動在內部建立一個var this = new object
3、工廠模式
建立一個函數,在函數內在建立一個對象並將對象返回,而不須要象構造的數同樣須要new出來一個對象,由於函數返回的是一個對象因此賦給一個變量就能夠直接使用
1 function createPerson(name, age, job){ 2 var o = new Object(); 3 o.name = name; 4 o.age = age; 5 o.job = job; 6 o.sayName = function(){ 7 alert(o.name); 8 } 9 10 return o; 11 } 12 13 var por = createPerson("haha", 20, "人人"); 14 var join = createPerson("heihei", 30, "360"); 15 console.log(por.sayName()); 16 console.log(por.sayName());
一、何時使用工廠模式:
一、對象的構建十分複雜 二、須要依賴具體的環境,建立不一樣的實例 三、處理大量具備相同的屬性的小對象
若是功能小就不適合用工廠模式,使得程序複雜
二、工廠模式存在的問題:
對象的方法都是單獨存放,構造函數的原型prototype能夠解決這種狀況.
function createPerson(name, age){ var obj = new Object(); obj.name = name; obj.age = age; obj.showName = function(){ alert(this.name); } obj.showAge = function(){ alert(this.age); } return obj; } var c1 = createPerson("siguang", 30); var c2 = createPerson("lulu", 27); c1.showName(); c2.showName(); alert(c1.showName == c2.showName); // 返回false,說明每次調用都會單獨存放這樣會佔用資源,若是使用構造函數就不會存這種狀況
4、橋接模式
在實現API的時候橋接模式很是有用,
橋接模式的做用在於,將抽象與實現分離,之後便兩者獨立變化
1 addEevent(element, "click", getBeerById(e)) 2 3 function getBeerById(id, callback){ 4 var id = this.id; 5 asyncRequest('GET', 'beer.uri?id=' + id, function(resp){ 6 // Callback response. 7 console.log('Requested Beer: ' + resp.responseText); 8 }) 9 } 10 11 function asyncRequest(type, data, callback){}
// 方法的鏈式調用
把方法串鏈起來調用,象Jquery同樣,$("#name").find("span").addClass("active");
這種技術分爲兩部分:一、建立表明HTML元素的工廠(工廠模式) 二、
// 使用單例模式和構造函數的區別
1 <script> 2 // 使用對象直接量(單體模式)和構造函數的區別 3 // 對象直接量 4 var Obj = { 5 getName: "10", 6 7 selectName: function(){ 8 alert(this.getName); 9 this.getName+=10; 10 } 11 } 12 13 $("#btn1").click(function(){ 14 Obj.selectName(); // 每點擊一次getName都累加10 15 }) 16 17 $("#btn2").click(function(){ 18 Obj.selectName(); // 每點擊一次getName都累加10 19 }) 20 21 22 // 構造函數 23 function Obj(){ 24 this.getName = 10; 25 } 26 27 Obj.prototype.selectName = function(){ 28 alert(this.getName); 29 this.getName+=10; 30 } 31 32 var n1 = new Obj(); 33 var n2 = new Obj(); 34 $("#btn1").click(function(){ 35 n1.selectName(); // 每點擊一次n1下的getName都會加10 36 }) 37 38 $("#btn2").click(function(){ 39 n2.selectName(); // 每點擊一次n2下的getName都會加10 40 }) 41 </script>
模塊方式一
1 var singleton = function(){ 2 // 私有屬性 3 var parive = 0; 4 5 // 私有方法 6 function getParive(){ 7 console.log(parive); 8 } 9 10 function getName(){ 11 console.log("siguang"); 12 } 13 14 return { 15 getParive: getParive(), 16 getName : getName() 17 } 18 }() 19 20 singleton.getParive; // 調用
模塊方法二:
1 (function(){ 2 var name = "siguang"; 3 4 function Person(val){ 5 this.name = val; 6 } 7 8 Person.prototype.getName = function(){ 9 console.log(this.name); 10 } 11 12 var newObj = new Person(name); 13 newObj.getName(); 14 })()
分發js庫的一個不可缺乏的方面是壓縮來節省帶寬,有三種類型的壓縮器:
一、簡單的刪除空格和換行和註釋,公保留主要的代碼
二、刪除空白註釋,也同將全部的變量名變得改短的壓縮
三、刪除空白和註釋,同時還最小化代碼中的全部單詞(不只是變量名)的壓縮器
兩種不一樣的庫:JSMin和Paker
JSMin:刪除無關的非代碼 Paker:屬於第三類完全壓縮全部單詞