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~

相关文章
相关标签/搜索