[js]03js设计模式01

来源:互联网 发布:淘宝上首页多少钱 编辑:程序博客网 时间:2024/06/06 00:58

单例设计模式

传统问题:

var name = "zhagsan";var age = 22;var name = "wangwu";age=18

存在覆盖问题.

于是多了对象类型进行分装隔离.

var person1={    name :"zhagsan",    age: 22}var person2={    name :"wangwu",    age: 28}

其中person1 person2在单例模式中被称为命名空间.

单例模式:
- 把描述同一个事务(同一个对象)的属性和方法放在一个内存空间下,起到分组的作用.这样不同事务质检的属性即使属性名相同,也不会冲突.

单例模式–模块化开发

  • 本ns调用其他ns的方法
  • 本ns调用本ns的方法
// 公共方法var utils = {    select:function () {    }};var tabRender={    change: function () {        utils.select(); //调用别的ns的方法    }};var searchRender={    change: function () {        // searchRender.clickEven();        this.clickEven(); //调用自己的方法  好处:改动对象名里面不用改,这里this是谁还不知道    }    clickEven:function () {    }};searchRender.change(); //不过一般外边都是这样调用的,所以....this是searchRender

工厂模式

var jsPerson1={    name: "wangwu",    age:22,    writeJs:function () {        console.log("myname is "+ this.name+",i can write js lala")    }}var jsPerson2={    name: "zhangsan",    age:22,    writeJs:function () {        console.log("myname is "+ this.name+",i can write js lala")    }}

如果有50多个人,那么要一个个创建吗?

    /*    * 工厂模式: 解决不能批量生产,它是一个破函数,把实现相同功能的属性拿出来放到一个函数里了,我们把这种方式也叫函数的封装。但是工厂模式不能解决实例识别的问题    * 面向对象:函数的封装,继承(子类继承父类的方法和属性等,祖传),多态:包括重载和重写,js中只有重写,但是却可以模拟重载.    * */
function createJsPerson(name,age){    var obj = {}    obj.name="wangwu";        obj.age=22;        obj.writeJs=function () {            console.log("myname is "+ this.name+",i can write js lala")        };}var p1 = createJsPerson("wangwu","22");p1.writeJs();var p2 = createJsPerson("zhangsan","23");p2.writeJs();
  • 单例模式实现了隔离,但是不能实现批量生产,授予手工业模式.
  • 工厂模式–批量生产,提高效率
  • 把实现同一件事情的相同的代码放到一个函数中,以后如果在想实现这个功能,不需要从心的编写这些代码了,只需要执行当亲啊的函数即可, 函数的封装—->”低耦合高内聚”,减少了代码的冗余.提高代码重复使用率

oop三大特性

  • 封装–工厂模式
  • 继承: 子类继承父类的属性和方法
  • 多态: 当前方法的多种形态,–包含重写和重载

其他后台语言中的重载:函数名相同,参数个数或类型不同,调用方法时候,自适应.

public void sum(int num1,int num2){};public void sum (Stirng num1,num2){};sum(100);sum(100,200);

在js中存在预加载的过程,因此,不存在函数重载

方法名字一样的话,后面的会把前面的覆盖掉,最后只保留一个

function sum(num1) {};function sum(num1,num2) {};sum(100);sum(100,200);
  • 重写: 子类重写父类的方法

js中的假重载,也是根据类型

function sum(sum) {    if (typeof num === "undefined"){        return 0;    }    return num;}sum(199);sum();

工厂函数模型

function CreateJsPerson(name,age) {    var obj = {};    obj.name = name;    obj.age=age;    obj.writeJs=function () {        console.log("my name is "+ this.name+",i can write js lala");    };    return obj;}var p1 = CreateJsPerson("maotai",22);p1.writeJs();var p2 = CreateJsPerson("liuyifei",18);p2.writeJs();

构造函数

  • 构造函数模式的目的就是为了创建一个自定义类,并且围着个类创建实例

构造函数和工厂函数的区别

  • 1,执行时候
    • 普通函数执行-> CreateJsPerson();
    • 构造函数执行-> new CreateJsPerson();
    • 通过new后CreateJsPerson就是一个类了.
    • 而函数执行的返回值(p1)就是CreateJsPerson这个类的实例

创建一个数组—类比系统内置的类

var ary = [] //字面量方法创建var ary = new Array(); //构造函数方法创建

不管哪一种方式ary都是Array这个类的一个实例.

特点1

  • js中所有的类都是函数数据类型的,它通过new执行变成1个类,但是他本身是一个普通的函数
  • js中所有的实例都是对象数据类型

特点2:

  • 在构造函数总,类中(函数体中)出现的this.xxx=xxx中的this代表当前类的一个实例

特点3:

  • p1和p2都是CreateJsPerson()的1个实例,所以都拥有writeJs这个方法,但是不同实例质检的方法是不一样的
  • 在类中给实例增加的属性(this.xxx=xxx)属于当前实例的一个私有属性,实例和实例之间是单独的个体,所以私有的属性是不相同的.
var p1 = new CreateJsPerson("maotai",22);p1.writeJs(); // ->this p1var p2 = new CreateJsPerson("maming",22);p2.writeJs();console.log(p1.writeJs===p2.writeJs);

以下这样写没有写return所以 res=undefined且CreateJsPerson中的this是window.

var res = CreateJsPerson("maming",22);
var p1 = new CreateJsPerson("maotai",22);
  • p1是对象类型
  • CreateJsPerson是一个类.–函数数据类型

  • 2.在函数执行代码执行的时候

    • 相同: 都是形成一个私有的作用域,然后形参赋值–>预解释–>代码从上到下执行;
    • 不同: 在代码执行前,不用自己在手动创建对象了,浏览器会自动创建一个对象数据类型值(这个类其实就是我们当前类的一个实例)
    • 接下来,代码从上到下执行,以当前的实例为执行的主体(this代表当前实例),然后分别把属性名和属性值赋给当前实例
    • 最后浏览器把默认创建的实例返回
function CreateJsPerson(name,age) {    //p1={}; //浏览器默认自动隐式创建了和实例同名的对象    this.name = name;    this.age=age; //这里this表示p1    this.writeJs=function () {        console.log("my name is "+ this.name+",i can write js lala"); //这里this表示谁调用它就是谁    };}var p1 = new CreateJsPerson("maotai",22);p1.writeJs();

特点:
- 没了创建对象语句
- 没了return语句
- 隐含了p1={}

构造函数扩展

  • 1,在构造函数模式总,Fn()执行,如果Fn不需要传递参数的话,后面的()可以省略
function Fn() {}// var f1 = new Fn();var f1 = new Fn;
  • 2, this的问题
    • 在类中出现this.xxx=xxx中的this都是当前类的实例
    • 而某个属性值(方法),方法中的this需要看方法执行时候,前面是否有”.”才知道this代表谁.
function Fn() {    // this -> f1    this.x=100;    this.getX=function(){        // this -> 需要看getX执行时候才知道        console.log(this.x);    }}var f1 = new Fn;f1.getX(); // this-->f1var ss= f1.getX(); ss();  // this-- window---undefined
  • 类有普通函数的一面,当函数执行的时候,var num其实只是当前形成私有作用域的私有变量而已,他和我们的f1这个实例没有任何关系;只有this.xxx=xxx才相当于给f1这个实例增加私有属性和方法.才和我们的f1有关系.
function Fn() {    var num = 100;    this.x=100;   // f1.x=100    this.getX=function(){  // f1.getX = function....        console.log(this.x);    }}var f1 = new Fn;console.log(f1.num); // undeifinedconsole.log(f1); // 打印属性和方法
  • 返回值覆盖问题

情况1:返回数值型–不受影响

function Fn() {    var num = 100;    this.x=100;    this.getX=function(){        console.log(this.x);    }    return 100;}var f1 = new Fn;console.log(f1);

情况2:返回对象类型–会覆盖

function Fn() {    var num = 100;    this.x=100;    this.getX=function(){        console.log(this.x);    }    return {name:"maming"}}var f1 = new Fn;console.log(f1);
  • 4,在构造函数模式中,浏览器会默认的把我们的实例返回(返回的是一个对象数据类型的值);如果我们手动写了return语句:
    • 返回的是一个基本数据类型的值,当前实例是不变的,例如,return 100;我们的f1还是当前Fn类的实例
    • 返回的是一个引用数据类型的值,当前的实例会被自己的返回值给替换掉,例如return {name:”zhufeng”}

检测实例是否属于某个类

function Fn() {    this.x=100;    this.getX=function(){        console.log(this.x);    };}var f1 = new Fn;
console.log(f1 instanceof Fn); //trueconsole.log(f1 instanceof Array); //falseconsole.log(f1 instanceof Object); //true

因为所有的实例都是对象数据类型的,而每一个对象数据类型都是object这个内置类的一个实例,所以f1也是它的一个实例.

对于检测数据类型来书,typeof有自己的局限性,不能细分object下的对象数据和真正则.

var a = [];console.log(a instanceof Array); // true 说明a是一个数组.

f1和f2都是Fn这个类的一个实例,都有x和getX2个属性,但是这2个属性是各自的私有属性,所以:

function Fn() {    this.x=100;    this.getX=function(){        console.log(this.x);    };}var f1 = new Fn;var f2 = new Fn;console.log(f1.get===f2.getX);//false

in 检测某一个属性是否属于这个对象 attr in object,不管私有属性还是共有属性,只要有,则都是true

function Fn() {    this.x=100;    this.getX=function(){        console.log(this.x);    };}var f1 = new Fn;console.log("getX" in f1);//true

hasOwnProperty:用来检测某一个属性是否为这个对象的”私有属性” 这个方法只能检测到私有的属性.

console.log(f1.hasOwnProperty("getX")); //true "getX" f1的私有属性

检测某一个属性是否为该对象的”共有属性” hasPubProperty

function hasPubProperty(attr,obj) {    return (attr in obj) && !obj.hasOwnProperty(attr):}console.log(hasPubProperty(f1,"getX")); //false

isPrototypeOf

原创粉丝点击