js高級語法之模式

js模式

模式應該算是js比較高級的語法了吧。 細細數來,有什麼,構造函數模式,原型模式,訂閱者模式,blablabla~
前幾天在面試鵝廠的時候,也被問及事件模型和模式的問題。 平時用jquery用的爽啊, 什麼on,delegate,trigger常常敲,可是大公司就是大公司,要的就是基礎紮實的淫。 事件模式改天在*, 今天咱們來講說模式之辯。jquery

模式之辯

常常聽人說,js是一個OO的語法,一切皆是對象。可是誰**又知道你說的是什麼意思呢? 騷俠磨嘰,之因此這樣說,是由於在js中,對象其實就是一個散列表(key/value).面試

var obj = {
    name: "I am an Object",
    ability:function(){
        console.log(this.name);
    }
}
obj.ability();

這應該算是一個基本的對象了,基本功能仍是有的。 之因此說起這個東西,就是由於在js中有不少概念都和對象有關,因此在這裏就先給你們一個impression吧.
切入主題ajax

工廠模式

寫過代碼有必定時間的淫應該都會了解一下這個模式吧。 其實說白的就是封裝,將一段重用性高的代碼,封裝起來,以便屢次調用。
老闆來個栗子~
好嘞~json

function Person(name,gender,age){
    var obj = new Object();
    obj.name = name;
    obj.gender = gender;
    obj.age = age;
    return obj;
}
var jimmy1 = Person("jimmy1","male",18);
var jimmy2 = Person("jimmy2","male",19);
console.log(jimmy1.name);  //jimmy1
console.log(jimmy2.name); //jimmy2

能夠看到上面演示的, 將一個person給封裝起來,能夠建立無數多我的。 我操,那我之後就能夠用這個寫阿喂。
額~ 能夠是能夠,不過有點 waste . 並且不能很好的說明你建立的究竟是個什麼東西,咱們使用typeof,以及instanceof 來檢驗一下.app

console.log(typeof jimmy1);  //"object"
console.log(jimmy1 instanceof Object);  //true
console.log(jimmy1 instanceof Person);  //false

咱們細細看一下, 上面例子中,每一個人都建立了一個Obejct() 的實例, 而後添加屬性,方法,最後再返回。 這樣寫簡單明瞭,可是咱們是有技術潔癖的人。 因此咱們要提取公因式,將重複的代碼再提出出來。 比較官方的說法叫作,構造函數模式~函數

構造函數模式

構造函數~ 是什麼勒。 我們不弄虛的。this

take is cheap, show me u codeurl

function Person(name,gender,age){
    this.name = name;
    this.gender = gender;
    this.age = age;
}
var jimmy1 = new Person("jimmy1",'male',18);
jimmy1.name;  // jimmy1
var jimmy2 = new Person("jimmy2",'male',18);
jimmy2.name;  // jimmy2

這就是一個超級典型的構造函數模式, 有 this,有參數,有new,還有實例。
構造函數的原理其實和工廠模式的原理同樣,就是建立一個對象,而後添加對應的屬性和方法.
構造函數不是函數嗎?怎麼和對象扯上關係了。 別忘了咱們開篇說起的 一切皆是對象。 咱們來理一理過程:prototype

(1)建立一個新對象。 // new Person(); 的做用
(2)將構造函數的做用域賦給新對象 //就是將this指向這個對象, 至關於上例中的obj
(3)執行構造函數裏面的內容 //給新對象添加方法和屬性, this就是你建立的Obj
(4)返回新對象 //就是Obj了

哈哈~ 是否是以爲寫代碼,也能夠寫出藝術的感受嘞~
其實構造函數模式應該算是工廠模式的一個升級版。 在每一個實例上,會存在一個constructor的屬性,來表示該對象的類型.指針

console.log(jimmy1.constructor);  //Person
console.log(jimmy1 instanceof Person);  //true

這樣我總算能夠知道我建立的是否是 一我的了。
但實際的狀況是,我建立的是一個靜態的人,他的動做我該怎麼完成。 加唄~

function Person(name,gender,age){
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.speak = function(){
        console.log("my name is " +this.name);
    }
}
var jimmy1 = new Person("jimmy1",'male',18);
jimmy1.speak();  //my name is jimmy1

恩,這樣啊~ 一門高級語言,永遠不會讓你知道你不知道。
想想,和工廠模式是一個道理,每次建立一個實例,我都得實例一個對象,並且記住函數也是對象。
上面的例子中,我在建立Person的實例時, 因爲內部還有一個speak的函數,我還得建立另一個speak的實例對象。並且這些實例都是建在哪裏勒,呵呵,你的內存中~
實際狀況是,若是我建立了>1000 我的, 我比A bra 還小的4G內存怎麼活啊。 js 用於不會讓你失望的。
在社區的衍生中,出現了另一個變體: 原型模式
(Ps:這是我在面試鵝廠的時候,一個經典問題)

原型模式

說起原型模式,就必須說明一下原型這個概念。想想咱們建立對象的時候作了什麼~

var obj = new Object();

其實上面的寫法,是建立了一個實例對象,而且包含了原型對象(Object)上面的全部方法.
好比說:

obj.toString(); //轉換字符串的方法

總結一下,原型模式其實就是,提供一些列共有的屬性和方法 的模式。
來個栗子:

function Person(){
}
Person.prototype.name="jimmy";
Person.prototype.gender="male",
Person.prototype.outName = function(){
    console.log(this.name);
}
var jimmy = new Person();
jimmy.outName;  //jimmy

。。。好難看啊~
看只是表面,咱們來講說內在。 原型模式的內涵超級豐富。 在原型模式中,新增了一個東西prototype(原型), 這就是原型模式的精華。
上面說了構造函數新增了constructor做爲表示符,原型模式裏面有prototype做爲頂樑柱.
prototype(原型)就是一個指針,用來指向一個對象,而且這個對象是全部實例共有的原型對象.
而這個原型模式和構造函數模式的最重要的一個卻別就是。this指針的指向問題.
使用構造函數模式,這個this指針指向的是構造函數裏面的this.
而使用原型模式,這個this是指向 原型對象(prototype);
我操~不理解啊~ 磨嘰,待我細細解釋.

細說原型模式

其實建立原型的方法也是使用構造函數,只是每一個函數建立的時候會自帶一個prototype屬性指向函數的原型對象。並且prototype上還有一個constructor用來指向 該構造函數中的this. 這樣, 原型對象上面就有了和 構造函數的鏈接。
咱們能夠檢驗一下:

//一樣一個例子
function Person(){
}
Person.prototype.name="jimmy";
Person.prototype.gender="male",
Person.prototype.outName = function(){
    console.log(this.name);
}
var jimmy = new Person();
console.log(jimmy.constructor); //Person
console.log(Person.prototype.constructor);  //Person

如今咱們只要知道Person.prototype就是表明Person的原型,that's enough~
關於__proto__,prototype,constructor後面我會專門獨立出來講明的。
留個坑,寫完了放一個連接.
說了這麼多,濛濛噠~
來,總結一下實例與構造函數模式以及原型模式之間的聯繫:

原型模式 實例<--->構造函數的原型對象
構造函數模式: 實例<--->構造函數

這樣應該差很少能理解吧。 盡力了~
可是,一門高級的語言不會讓你知道你不知道.
實際上,使用原型的坑也是不少的。重用性解決了,可是自定義卻不能實現了。
然而這只是一小部分,給你來個大的。
原型模式之引用類型的坑

talk is cheap, show me u code

function Person(){}
Person.prototype.wife = {
    "Sheily":{
        age:23,
        height:170
    },
    "Adel":{
        age:20,
        height:172
    }
}
var jimmy = new Person();
console.log(jimmy.wife);  //兩我的
var sam = new Person();
sam.wife.angela = {
    age:24,
    height:18-
}
console.log(sam.wife);  //3我的
console.log(jimmy);  //3我的

這樣就能看出明顯的區別。 想一想吧,老婆能是別人的嗎?
聰明的社區 scratch their butt。 而後想到,構造函數模式和原型模式一塊兒用不久over了嗎?
我操~~~ 真聰明. 取個名字吧,混合模式~(本身編的 :)

混合模式

經過上例的說明,相信你們應該能理解我所說的,原型模式 is not versatile.
所謂的混合就是將二者結合在一塊兒:
構造函數定義的是實例的屬性,而原型模式定義的是共享的屬性(prototype).
來個栗子:

function Person(name,wife){
    this.name = name;
    this.wife = wife;
}
Person.prototype.myWife = function(){
    console.log(this.wife);
}
var jimmy = new Person("jimmy",{
    sheriy:{
        age:19,
        height:180
    }
});

jimmy.myWife();  //sheriy
var sam = new Person('sam',{
    angela:{
        age:20,
        height:190
    }
})
sam.myWife(); // angela

不再用擔憂本身的老婆是別人家的了。
這種方式,應該是js社區極力推崇的。可是咱們寫項目的時候,說實話,真心用不到(由於咱們的項目過小了)。因此在這裏推薦一個,我本身常用的。 字面量模式的寫法.

字面量模式

直接上栗子:

var login = {
    userName : document.querySelector('#userName'),
    ps: document.querySelector('#password'),
    loginBtn: document.querySelector('#loginBtn'),
    init:function(){
        var _this = this;
        this.loginBtn.addEventListener("click",function(){
            var name = _this.userName.getAttribute("value"),
                ps = _this.ps.getAttribute('value');
            http.ajax({
                url:Pathurl.login,
                dataType:'JSON',
                contentType:"application/json"
            })
            .then(function(data){
                //請求成功後的相關操做
            })
        },false);
    }
}
login.init();

這應該算是一個基本的寫法吧。 本人青睞於這種寫法的緣由是,他有一個入口函數,init(),並且獲取元素後,能夠重複性的使用,方便你每次添加元素的時候從新獲取(想一想個人4G內存,你們仍是不要這麼作了吧).ending~

相關文章
相關標籤/搜索