面向对象、原型链(22)

单例设计模式的理论模型

/*

 * 单例设计模式(singleton pattern)

 *  1.表现形式

 *  var obj = {

 *      xxx:xxx,

 *      ...

 *  };

 *  在单例设计模型中,OBJ不仅仅是对象名,它被称为“命名空间[NameSpace]”,把描述事务的属性存放到命名空间中,多个命名空间是独立分开的,互不冲突

 *

 *  2.作用

 *  =>把描述同一件事务的属性和特征进行“分组、归类”(存储在同一个堆内存空间中),因此避免了全局变量之间的冲突和污染

 *  var pattern1={name:'xxx'}

 *  var pattern2={name:'xxx'}

 *

 *  3.单例设计模式命名的由来

 *  =>每一个命名空间都是JS中Object这个内置基类的实例,而实例之间是相互独立互不干扰的,所以我们称它为“单例:单独的实例”

 */ 

var name = "李清";
var age = 18;
var sex = "girl";

var name = "张三";
var age = 20;
var sex = "boy";

/*

 * 高级单例模式

 *   1.在给命名空间赋值的时候,不是直接赋值一个对象,而是先执行匿名函数,形成一个私有作用域AA(不销毁的栈内存),在AA中创建一个堆内存,把堆内存地址赋值给命名空间

 *

 *   2.这种模式的好处:我们完全可以在AA中创造很多内容(变量OR函数),哪些需要供外面调取使用的,我们暴露到返回的对象中(模块化实现的一种思想)

 */

var nameSpace = (function () {

    var n = 12;
    function fn() {
        //...
    }
    function sum() {


    }
    return {
        fn: fn,
        sum: sum
    }
})();

THIS

    1.给当前元素的某个事件绑定方法, 当事件触发方法执行的时候,方法中的THIS是当前操作的元素对象

oBox.onclick=function(){
   //=>this:oBox
}

  2.普通函数执行,函数中的THIS取决于执行的主体,谁执行的,THIS就是谁(执行主体:方法执行,看方法名前面是否有“点”,有的话,点前面是谁this就是谁,没有this是window)

     function fn(){//=>AAAFFF000
        console.log(1);
     }
     var obj={
        fn:fn //=>fn:AAAFFF000
     };

     //=>执行的是相同的方法(不同地方在于函数执行方法中的this是不一样的)
     obj.fn();//=>this:obj
     fn();//=>this:window

     //=>自执行函数执行,方法中的this是window
     ~function(){
         //=>this:window
     }();
var n = 2;
var obj={
    n:3,
    fn:(function (n) {
        n*=2;
        this.n+=2;
        var n=5;
        return function (m) {
            this.n*=2;
            console.log(m + (++n));
        }
    })(n)//=>obj.n会报错
};
var fn = obj.fn;
fn(3);//=>9
obj.fn(3);//=>10
console.log(n, obj.n);//=>8 6


实战项目中的模块化

/*

 * 模块化开发

 *   1.团队协作开发的时候,会把产品按照功能板块进行划分,每一个功能板块有专人负责开发

 *   2.把各个版块之间公用的部门进行提取封装,后期在想实现这些功能,直接的调取引用即可(模块封装)

 */

var utils=(function () {
    return {
        aa:function () {

        }
    }
})();

//=>成员1
var skipRender = (function () {
    var fn = function () {
        //...
    };
    //...
    return {
        init: function () {

        },
        fn:fn
    }
})();
skipRender.init();

//=>成员2
var weatherRender = (function () {
    var fn = function () {

    };
    return {
        init: function () {
            fn();//=>调取自己模块中的方法直接调取使用即可
            skipRender.fn();//=>调取别人模块中的方法
        }
    }
})();
weatherRender.init();

工厂模式

/*

 * 工厂模式(Factory Pattern)

 *   1.把实现相同功能的代码进行“封装”,以此来实现“批量生产”(后期想要实现这个功能,我们只需要执行函数即可)

 *

 *   2.“低耦合高内聚”:减少页面中的冗余代码,提高代码的重复使用率

 */

function createPerson(name, age) {
    var obj = {};
    obj.name = name;
    obj.age = age;
    return obj;
}

var p1 = createPerson('xxx', 25);
var p2 = createPerson('xxx', 25);

面向对象编程(Object Oriented Programming)

/*

 * JS是一门编程语言(具备编程思想)

 *   [面向对象]

 *      JS\JAVA\PHP\C#\Ruby\Python\C++...

 *

 *   [面向过程]

 *      C

 *

 * 面向对象编程,需要我们掌握:“对象、类、实例” 的概念

 *   对象:万物皆对象

 *   类:对象的具体细分(按照功能特点进行分类:大类、小类)

 *   实例:类中具体的一个事物(拿出类别中的具体一个实例进行研究,那么当前类别下的其它实例也具备这些特点和特征)

 *

 * 整个JS就是基于面向对象设计和开发出来的语言,我们学习和实战的时候也要按照面向对象的思想去体会和理解

 */


创建值的两种方式以及区别

/*

 * 基于构造函数创建自定义类(constructor)

 *   1.在普通函数执行的基础上“new xxx()”,这样就不是普通函数执行了,而是构造函数执行,当前的函数名称之为“类名”,接收的返回结果是当前类的一个实例

 *

 *   2.自己创建的类名,最好第一个单词首字母大写

 *

 *   3.这种构造函数设计模式执行,主要用于组件、类库、插件、框架等的封装,平时编写业务逻辑一般不这样处理

 */

function Fn() {

}

Fn();//=>普通函数执行
var f = new Fn();//=>Fn是类 f是类的一个实例
var f2 = new Fn();//=>f2也是Fn的一个实例,f2和f是独立分开的,互不影响*/

/*

 * JS中创建值有两种方式

 *   1.字面量表达式

 *   2.构造函数模式

 */

// var obj = {};//=>字面量方式
// var obj = new Object();//=>构造函数模式
// //=>不管是哪一种方式创造出来的都是Object类的实例,而实例之间是独立分开的,所以 var xxx={} 这种模式就是JS中的单例模式

//=>基本数据类型基于两种不同的模式创建出来的值是不一样的
//> 基于字面量方式创建出来的值是基本类型值
//> 基于构造函数创建出来的值是引用类型
//->NUM2是数字类的实例,NUM1也是数字类的实例,它只是JS表达数字的方式之一,都可以使用数字类提供的属性和方法
var num1 = 12;
var num2 = new Number(12);
console.log(typeof num1);//=>"number"
console.log(typeof num2);//=>"object"

构造函数执行的机制

//=>普通函数执行

//1.形成一个私有的作用域

//2.形参赋值

//3.变量提升

//4.代码执行

//5.栈内存释放问题

function Fn(name, age) {
    var n = 10;
    this.name = name;
    this.age = age + n;
}

//=>普通函数执行
Fn();

//=>构造函数执行
var f1 = new Fn('xxx', 20);
var f2 = new Fn('aaa', 20);

console.log(f1 === f2);//=>false:两个不同的实例(两个不同的堆内存地址)
console.log(f1.age);//=>30
console.log(f2.name);//=>'aaa'
console.log("name" in f1);//=>true name&age在两个不同的实例都有存储,但是都是每个实例自己私有的属性
console.log(f1.n);//=>undefined 只有this.xxx=xxx的才和实例有关系,n是私有作用域中的一个私有变量而已(this是当前类的实例)

 * 构造函数执行,不写RETURN,浏览器会默认返回创建的实例,但是如果我们自己写了RETURN?

 *   1.return是的一个基本值,返回的结果依然是类的实例,没有受到影响

 *   2.如果返回的是引用值,则会把默认返回的实例覆盖,此时接收到的结果就不在是当前类的实例了

 *

 *   =>构造函数执行的时候,尽量减少RETURN的使用,防止覆盖实例

function Fn() {
    var n = 10;
    this.m = n;
    // return;//=>这样RETURN是结束代码执行的作用,并且不会覆盖返回的实例
    // console.log(1);
}

var f = new Fn();//=>new Fn;  在构造函数执行的时候,如果Fn不需要传递实参,我们可以省略小括号,意思还是创建实例(和加小括号没有区别)
console.log(f);

检测方法扩展

//=>instanceof:检测某一个实例是否隶属于这个

// console.log(f instanceof Fn);//=>TRUE
// console.log(f instanceof Array);//=>FALSE
// console.log(f instanceof Object);//=>TRUE (万物皆对象:所有的对象,包含创建的实例都是Object的实例)

//=>in:检测当前对象是否存在某个属性(不管当前这个属性是对象的私有属性还是公有属性,只要有结果就是TRUE)

// console.log('m' in f);//=>TRUE
// console.log('n' in f);//=>FALSE
// console.log('toString' in f);//=>TRUE toString是它的公有属性

 //=>hasOwnProperty:检测当前属性是否为对象的私有属性(不仅要有这个属性,而且必须还是私有的才可以)

// console.log(f.hasOwnProperty('m'));//=>TRUE
// console.log(f.hasOwnProperty('n'));//=>FALSE 连这个属性都没有
// console.log(f.hasOwnProperty('toString'));//=>FALSE 虽然有这个属性但是不是私有的属性
//=>思考题:编写一个方法hasPubProperty,检测当前属性是否为对象的公有属性,和hasOwnProperty对应
function hasPubProperty(obj, attr) {
    //=>OBJ:要检测的对象
    //=>ATTR:要检测的属性
    //...
}
hasPubProperty(f, 'm');//=>FALSE
hasPubProperty(f, 'n');//=>FALSE
hasPubProperty(f, 'toString');//=>TRUE

原型链和原型链的查找机制

 * 原型(prototype)、原型链(__proto__)

 *

 *  [函数]

 *    普通函数、类(所有的类:内置类、自己创建的类)

 *

 *  [对象]

 *    普通对象、数组、正则、Math、arguments...

 *    实例是对象类型的(除了基本类型的字面量创建的值)

 *    prototype的值也是对象类型的

 *    函数也是对象类型的

 *    ...

 *  1.所有的函数数据类型都天生自带一个属性:prototype(原型),这个属性的值是一个对象,浏览器会默认给它开辟一个堆内存

 *  2.在浏览器给prototype开辟的堆内存中有一个天生自带的属性:constructor,这个属性存储的值是当前函数本身

 *  3.每一个对象都有一个__proto__的属性,这个属性指向当前实例所属类的prototype(如果不能确定它是谁的实例,都是Object的实例)

function Fn() {
    var n = 100;
    this.AA = function () {
        console.log(`AA[私]`);
    };
    this.BB = function () {
        console.log(`BB[私]`);
    };
}
Fn.prototype.AA = function () {
    console.log(`AA[公]`);
};

var f1 = new Fn;
var f2 = new Fn;

console.log(f1.n);//=>undefined

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值