485 面向对象:单例设计模式,工厂模式,什么是面向对象,构造函数,instanceof,构造函数中的局部变量以及new构造函数时不加括号

1.1 单例设计模式

单例模式:把描述事务的信息放到一个命名空间中进行分组归类,防止全局变量的污染。

let name = '和冉';
let age = 18;
let sex = '美女';

let name = '小璐璐';
let age = 81;
let sex = '看着办';

// => 把描述当前事务特征的信息进行分组归类(减少全局变量的污染)
// => 这就是JS中的单例设计模式
/*
 * beautiGirl不仅仅被叫做变量(对象名),也被称为“命名空间”
 *   单例模式:把描述事务的信息放到一个命名空间中进行分组归类,防止全局变量的污染
 */
let beautiGirl = {
    name: '和冉',
    age: 18
};

let oldMan = {
    name: '小璐璐',
    age: 81
};

为了让单例模式变的高大上一些,项目中的单例模式都这样处理:【使用闭包】

function fn() { }
let namespace = (function () {
    // 创建一些方法(闭包中的私有方法)
    let fn = function () {
        // ....  
    };
    // ...
    return {
        name: 'xxx',
        fn: fn
    }
})();
namespace.name
namespace.fn();

例如:完成一个需要团队协作开发的案例(百度首页)

/*
 * 公共模块
 */
let utils = (function () {
    let queryElement = function () {... }

    return {
        //queryElement: queryElement
        queryElement
    }
})();

    
/*
 * XXX负责的页卡模块
 */
let pageTabModule = (function () {
    // => 获取元素(调取其它命名空间下的方法)
    let tabBox = utils.queryElement('.tabBox');
    let show = function () {... }
    ...
    return {
        init: function () {
            //调用自己模块下的方法
            show();
        }
    }
})();
pageTabModule.init();
    
...

1.2 工厂模式

批量化生产:把实现某个功能的代码进行封装,后期在想实现这个功能,我们直接执行函数即可

  • 低耦合:减少页面中冗余的代码
  • 高内聚:提高代码的重复使用率
function createPerson(name, age) {
    let person = {};
    person.name = name;
    person.age = age;
    return person;
}
let beautyGirl = createPerson('和冉', 18);
let oldMan = createPerson('小璐璐', 81);
beautyGirl.name
oldMan.name
...

1.3 什么是面向对象

把抽象的“对象”,按照特点进行详细分类(大类/小类),把共同的东西进行抽取,放到对应的类别中。
=> “类”是对“对象”的一种细分,以及对公共部分的封装。

类别中派生出来的具体的事务叫做类的“实例”。
实例既有属于自己私有的东西,也有继承各个类别中的共有信息。

面向对象编程,其实就是掌握“对象”、“类”、“实例”之间的关系、知识。
例如:类的封装、继承、多态。

控制台中,用dir()函数查看,dir(tabBox),tabBox是元素id


1.4 构造函数

构造原型模式(正统面向对象编程)

自己能够创造出自定义类和对应实例,构建起一套完整的面向对象模型

/* 
 * new CreatePerson()执行和普通函数执行的区别
 *   1.new这种执行方式叫做“构造函数执行模式”,此时的CreatePerson不仅仅是一个函数名,被称为“类”,而返回的结果(赋值给person1的)是一个对象,我们称之为“实例”,而函数体中出现的this都是这个实例
 */
function CreatePerson(name, age) {
    this.name = name;
    this.age = age;
}

// 普通函数执行模式
let zs = CreatePerson('张三', 25); // => 普通函数执行,this指向window,前面没有点
console.log(zs) // undefined,因为没有返回值
console.log(window.name, window.age) // 张三 25

// 构造函数执行模式
let person1 = new CreatePerson('和冉', 18);
console.log(person1) // CreatePerson {name: "和冉", age: 18}


手动修改构造函数中的this

function CreatePerson(name, age) {
    // this => person1
    this.name = name;
    this.age = age;
    // => 如果手动RETURN的是一个基本值,对返回的实例无影响。如果手动RETURN的是一个引用类型的值,会把默认返回的实例给替换掉(所以在构造函数模式执行下,我们一般都不要手动写RETURN,防止把返回的实例给替换)
    // return 100;  // => 返回的还是实例对象,不影响
    /* return {
    	xxx: 'xxx'
    }; */ 
}
let person1 = new CreatePerson('和冉', 18);
console.log(person1) // CreatePerson {name: "和冉", age: 18}


1.5 instanceof

instanceof:要求检测的实例必须是对象数据类型的,基本数据类型的实例是无法基于它检测出来的。【用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。】

/*
 *  instanceof:用来检测某个实例是否属于这个类
 *     实例 instanceof 类,属于返回TRUE,不属于返回FALSE
 *  [局限性]
 *     1.要求检测的实例必须是对象数据类型的,基本数据类型的实例是无法基于它检测出来的   
 */
console.log(person1 instanceof CreatePerson); // => TRUE,上例的
let ary = [12, 23];
console.log(ary instanceof Array); // => TRUE
console.log(ary instanceof RegExp); // => FALSE
console.log(ary instanceof Object); // => TRUE 
console.log(1 instanceof Number); // => FALSE ,因为 1不是对象类型 



//  --------------------------------



/*
 * 基本数据类型在JS中的特殊性
 *   1.一定是自己所属类的实例
 *   2.但是不一定是对象数据类型的 
 */
// 字面量创建方式(也是Number类的实例,也可以调取内置的公有方法)
let n = 10;
console.log(n.toFixed(2));
console.log(typeof n); // => "number"

// 构造函数创建模式(创建出来的实例是对象类型的)
let m = new Number("10");
console.log(m)
console.log(typeof m); // => "object"
console.log(m.toFixed(2)); // 10.00

1.6 构造函数中的局部变量以及new构造函数时不加括号

// 构造函数执行,因为也具备普通函数执行的特点,所以:
// 1.和实例有关系的操作一定是 this.xxx = xxx ,因为this是当前类创造出来的实例
// 2.私有变量和实例没有必然的联系
function Fn(n) {
    let m = 10;
    this.total = n + m;
    this.say = function () {
        console.log(this.total);
    };
}
let f1 = new Fn(10);
let f2 = new Fn(20);

// => new的时候不论是否加小括号,都相当于把Fn执行了,也创建了对应的实例,只不过不加小括号是不能传递实参的(当前案例中的形参n=undefined)
let f3 = new Fn; 

console.log(f1.m); // => undefined
console.log(f2.n); // => undefined
console.log(f1.total); // => 20
f2.say(); // => this指向f2,因为say执行前面有点, 输出30
console.log(f1 === f2); // => FALSE(因为是两个不同的实例对象,也就是不同的堆地址)
console.log(f3) // Fn {total: NaN, say: ƒ}

猜你喜欢

转载自www.cnblogs.com/jianjie/p/13199626.html