网站公告

最近任务:三方业务接入、低代码表单集成

主站地址: http://117.72.70.166/admin/

QQ群:972107977

Skip to content

JS 设计模式

2015 年 8 月第一版,作者:张容铭

面向对象编程

避免污染全局

  1. 将多个函数/变量放在一个变量(对象)中保存,减少覆盖或被覆盖的风险

    js
    let Obj1 = {}
    Obj.Fn1 = function(){}
    
    // 对象的另一种形式:js中函数也是对象
    let Obj2 = function(){}
    Obj2.Fn1 = function(){ ... }
    Obj2.Fn2 = function(){ ... }
    
    // 	为方便复用,通过函数返回值的形式创建,每次调用都是全新的,使用上互不影响
    let Obj3 = function(){
        return {
            Fn1:function(){},
            Fn2:function(){},
        }
    }
    let a = Obj3();
    a.Fn1();
    
    // 真正意义上的类,通过new关键字创建
    let Obj4 = function(){
        this.fn1=function(){...}
        this.fn2=function(){...}
    }
    let a = new Obj4();
    // 这样每次new创建都会产生一个新的对象,但this.创建方法会造成很多开销
    // 优化:利用原型链的继承关系,创建一次供后代持续使用
    Obj4.prototype.fn3=function(){}
    // 或者
    obj4.prototype={
        fn4:function(){},
        fn5:function(){}
    }
    // 注意:以上两种方法不要混合使用,避免覆盖之前的赋值

链式编程

js
// 链式调用的核心,就是函数在执行完成后,返回了this,即当前对象
let Obj = {
    fn1:function(){
        ... return this
    }
    fn2:function(){
        ... return this
    }
}
obj.fn1().fn2()

// 放到类的原型上时使用,需要先new一下再使用
let Obj2 =function(){}
Obj2.prototype = {
    fn1:function(){
        ... return this
    }
    fn2:function(){
        ... return this
    }
}
let obj2= new Obj2()
obj2.fn1().fn2()

利用原始类型

js
// 对 Function的原型进行操作,就可以让所有的函数都具有某个方法/属性
// 但依旧保持不能污染其他人使用的原则,可以单独创建一个使用
Function.prototype.addMethod=function(name,fn){
	this[name]=fn
    return this  // 返回this,可以实现链式添加
}

// 创建属于自己的函数
var methods = new Function()
methods.addMethod("checkName",function(){
    ...
    return this // 每个添加的函数都返回this,可实现方法的链式调用
})

知识卡:

  • 通过 this 添加的属性方法与 prototype 添加的属性方法有什么不同?
    • this 定义的属性或方法是该对象自身拥有,每次 new 新的对象都会重新创建
    • prototype 继承的属性在创建新的对象时,不会再次创建
  • 概念:
    • 私有属性/方法:由于 js 函数作用域,声明在函数内部的属性和方法外界访问不到(类.属性 也拿不到)
    • 共有属性/方法:在函数内部通过 this 创建的属性和方法 或 通过类通过 prototype 创建的属性/方法,在 new 创建对象时都会拥有一份并且可以被外界访问
      • 特权方法:通过 this 创建的方法,可以访问到函数内部的 私有属性和私有方法!
    • 静态共有属性/方法:在函数外部通过点语法创建的属性/方法,在 new 创建对象时并没有被执行到,new 创建的对象也无法获取他们,但能通过类来使用。
    • 静态私有属性/方法:通常借助闭包实现,
    • 构造器:在 new 创建对象时,调用特权方法初始化实例对象的一些属性,因此也叫类的构造器
    • new 关键字:通过 new 关键字创建对象,实质是对新对象 this 的不断赋值,并将 prototype 指向类的 prototype 所指向的对象。
  • 总结:
    • 静态-new 创建的对象中无法通过 this 访问
    • 私有-在类的外部无法直接访问但可以借助实例的特权方法操控
    • 共有-this 或 prototype 创建的属性/方法,在创建的实例中可以被访问
js
// 1.无静态私有方法/属性时:
var Book = function (id, name, price) {
  // 私有属性
  var num = 1;
  // 私有方法
  function checkId() {}
  // 公有属性
  this.id = id;
  // 特权方法-可以操作私有属性/方法  也是公有方法
  this.getName = function () {};
  this.setName = function () {};
  this.getPrice = function () {};
  this.getPrice = function () {};
  // 其他公有方法
  this.copy = function () {};
  // 构造器-new创建实例时可以初始化对象的一些属性
  this.setName(name);
  this.setPrice(price);
};

// 静态公有属性(new创建的对象无法访问)
Book.isChinese = true;
// 静态公有方法(new创建的对象无法访问)
Book.restTime = function () {};
Book.prototype = {
  // 公有属性
  isJsBook: false,
  // 公有方法
  display: function () {},
};

// 测试:
var b = new Book(11, "我的心只悲伤七次", 66);
console.log(Book.num, Book.isChinese); // undefined  true
console.log(b.num); // undefined
console.log(b.isJsBook); // false
console.log(b.id); // 11
console.log(b.isChinese); // undefined
js
// 2.借助闭包实现,实现静态私有属性/方法
let Book = (function(){
    // 静态私有变量
    var BookNum = 0
    // 静态私有方法
    function checkBook(name){}
    // 创建类
    function _book(newId,newName,newPrice){
        // 私有变量
        var name,price
        // 私有方法
        function checkId(){}
    	// 特权方法-可以操作私有属性/方法  也是公有方法
    	this.getName = function(){}
    	this.setName = function(){}
    	this.getPrice = function(){}
    	this.getPrice = function(){}
        //公有属性
        this.id=newId
        //公有方法
      	this.copy=function(){}

        bookNum++
        if(bookNum>100){ ... }

        // 构造器
        this.setName(name);
        this.setPrice(price);
	}
	// 构建原型
	_book.prototype={
		isJsBook:false, // 静态公有方法
		display:function(){} // 静态公有属性
	}

	return _book;  // 返回类
})()

安全模式-检察长

  • 在使用函数类的时候容易出现 创建实例时 遗忘 new 关键字而导致问题
  • 解决方法:使用不同情况下的不同现象,使用判断做区分并手动解决异常下的问题
js
var Book = function(){
    if(this instanceof Book){
        ... // 正常代码
    }else{
        return new Book()
    }
}

var book1 = new Book()
var book2 = Book()

创建型设计模式