封装JS函数库

1,409 阅读2分钟

一、 target:

  • 实现模块化开发
  • 避免全局变量污染

二、 实现

1、闭包实现
const Person = (function(){
    //共享变量
    let share_val = 'i am io';
    return function(name,age){
        let  _name = name, _age = age;
        this.setName = function(name){
            _name = name;
        }
        this.setAge = function(age){
            _age = age;
        }
        this.getName = function(){
            return _name;
        }
        this.getAge = function(){
            return _age;
        }
    }
})();
Person.prototype = {
    constructor:Person
    toString():function(){
        return `姓名:${this.getName()}; 年龄:${this.getAge()}`;
    }
}

const person_obj = new Person('rkxie',23);

  • 描述:用闭包模拟私有方法---模块模式
  • 缺点:setter&getter方法同样未定义在原型对象中,增加内存开销
  • 优点:共享公共变量&方法
2、对象实现
const Person = function (no,name,age) {
    let _no = no, _name = name, _age = age;
    return {
        setNo: function (no) {
            _no = no;
        },
        setName: function (name) {
            _name = name;
        },
        setAge: function (age) {
            _age = age;
        },
        getAge: function () {
            return _age;
        },
        getName: function () {
            return _name;
        },
        getNo: function () {
            return _no;
        },
        toString: function () {
            return `序号: ${this.getNo()};姓名: ${this.getName()}; 年龄: ${this.getAge()}`
        }
    }
};
const p1 = new Person('abc','def','fgh');
const p2 = Person('abc111','def111','fgh111');

上述new关键字创建的对象和通普通函数返回的对象能达到一致的效果,具体原因见下文相技术点。

3、约定优先原则
function Person(no,name,age) {
    this.setNo(no);
    this.setName(name);
    this.setAge(age);
}
Person.prototype = {
    constructor: Person,
    setNo:function(no){
        this._no = no;
    },
    getNo:function(){
        return this._no;
    },
    setName:function (name) {
        this._name = name;
    },
    getName:function () {
        return this._name;
    },
    setAge:function (age) {
        this._age = age;
    },
    getAge:function () {
        return this._age;
    }
};
  • 描述:约定所有私有变量以_开头
  • 优点:共享setter&getter
  • 定义的成员变量可直接访问(变量&方法都定义在原型对象上)
4、严格封装
function Person(no,name,age) {
    let _no = no,_name = name,_age = age;
    this.setNo = function(no) {
        _no = no
    };
    this.setName = function(name) {
        _name = name
    };
    this.setAge = function(age) {
        _age = age
    };
    this.getNo = function () {
        return _no;
    };
    this.getAge = function () {
        return _age;
    };
    this.getName = function(){
        return _name
    };
}
Person.prototype = {
    constructor:Person,
    toString:function () {
        return `学号: ${this.getNo()};姓名: ${this.getName()}; 年龄: ${this.getAge()}`;
    }
};
  • 构造函数中新建成员变量
  • 优点:所有成员变量都是能通setter&getter操作
  • 缺点:增加内存开销

三、相关技术点

1、this的绑定

基于调用点:谁调用指向谁

  • 隐式绑定
  • 显式绑定
    • apply
    • call
    • bind
  • 关键字new绑定
  • 箭头函数绑定
    • this的值是函数创建所在的对象 绑定优先级:箭头函数---》new关键字---》显式绑定---》隐式绑定---》默认绑定
2、关键字new

创建一个对象时new关键字所起的作用:

  • 创建一个空对象
    • var obj = {};
  • 将构造函数的作用域赋值给空对象,即:构造函数中的this指向空对象
    • obj.__ proto__ = Person.prototype
    • Person.call(obj)
    • 解释:这句话的意思是给新对象构造原型链,链到构造函数的原型对象,从而新对象就可以访问构造函数中的属性及方法
  • 执行构造函数中的代码,为新对象添加属性(call方法)
  • 如果构造函数中有返回值则返回,否则返回新对象(return obj)
    • 构造函数中有返回:如果返回的是object类型,则返回构造函数中的对象,如果返回除object以外的其他类型(undefined、null、Number、String...)则返回obj

实现一个new:

function Person(name) {
    this.name = name;
}

var obj  ={};
obj.__proto__ = Person.prototype;
CO.call(obj);
return obj;

或者

function myNew() {
    const constr = Array.prototype.shift.call(arguments);
    const obj = Object.create(constr.prototype);
    const result = constr.apply(obj, arguments);
    return result instanceof Object? result : obj;
}
const p = myNew(Person,'xrk');
3、定义一个构造函数---自定义规范
4、Object.create使用注意事项
5、constructor指针的作用
6、__ proto __的替代方案