(es5实现es6+5)使用es5来实现es6Class类

文章结构

  • 推荐阅读
  • 声明类与创建对象
    • 构造函数注意点
  • 给类添加属性和方法
    • 不好的实现方式
    • 可以使用的方式
  • 类实现继承
  • getter和setter
  • 私有属性兼最终代码

推荐阅读

es6Class讲解
new关键字原理模拟
对象的访问器属性与数据属性

声明类与创建对象

// 4.自定义构造函数创建对象
function CreateObj(cname, age) {
    this.cname = cname;
    this.age = age;
}
let obj = new CreateObj("zhangsan", 18)
console.log(obj);

构造函数注意点

不要写return,return一个基本数据类型没有效果,
return一个引用数据类型数据,每次new调用返回的就是return的引用数据类型数据。
// 不要写return,return一个基本数据类型没有效果
/* function CreateObj(cname, age) {
    this.cname = cname;
    this.age = age;
    return 123;
}
let obj = new CreateObj("zhangsan", 18) //CreateObj { cname: 'zhangsan', age: 18 } */

// 2.2 return一个引用数据类型数据,每次new调用返回的就是return的引用数据类型数据
function CreateObj(cname, age) {
    this.cname = cname;
    this.age = age;
    return []
}
let obj = new CreateObj("zhangsan", 18) //[]
console.log(obj);

给类添加属性和方法

不好的实现方式

function Obj(name, age) {
    this.name = name;
    this.age = age;
    this.eat = function() {
        console.log("吃个饭");
    }
}

const obj1 = new Obj("zhangsan", 12);
const obj2 = new Obj("lisi", 21);
console.log(obj1.eat == obj2.eat); // false
我们发现obj.eat 和 obj2.eat它们不相等,说明它们的引用指向的不是同一块
内存地址,那么我们每次new一个对象出来,都需要额外开辟一块空间吗?
显然这种方式不好。

可以使用的方式

function Obj(name, age) {
    this.name = name;
    this.age = age;
    this.__proto__.eat = function() {
        console.log("吃个饭");
    }
}

const obj1 = new Obj("zhangsan", 12);
const obj2 = new Obj("lisi", 21);
console.log(obj1.eat == obj2.eat); // true
function Obj(name, age) {
    this.name = name;
    this.age = age;
    Obj.prototype.eat = function() {
        console.log("吃个饭");
    }
}

const obj1 = new Obj("zhangsan", 12);
const obj2 = new Obj("lisi", 21);
console.log(obj1.eat == obj2.eat); // true

类实现继承

/* super关键字 第一个参数为父类,第二个参数为this指向,
第三个参数为传给父类的属性 */
function _super(Father, _this, args) {
    // 继承父类的属性
    Father.apply(_this, args);
    // 继承父类的方法
    _this.__proto__ = Father.prototype;
}

// 父类
function Person() {
    this.name = arguments[1];
    this.age = arguments[2];
    this.description = "哺乳动物";
    Person.prototype.eat = function() {
        console.log("吃个饭");
    }
}

// 第一个参数为谁的对象,第二个参数为姓名,第三个参数为年龄
function Obj() {
    _super(Person, this, arguments);
    // 谁的对象
    this.whoObject = arguments[0];

    this.__proto__.kiss = function() {
        console.log("亲吻" + this.whoObject);
    }
}

// 没错,帅逼有两个对象,羡慕啊~~
const obj1 = new Obj("帅逼", "zhangsan", 12);
const obj2 = new Obj("帅逼", "lisi", 21);
console.log(obj1); // { name: 'zhangsan', age: 12, description: '哺乳动物', whoObject: '帅逼' }
console.log(obj2); // { name: 'lisi', age: 21, description: '哺乳动物', whoObject: '帅逼' }
obj1.kiss(); // 亲吻帅逼
obj2.kiss(); // 亲吻帅逼
console.log(obj1.eat == obj2.eat); // true

(es5实现es6+5)使用es5来实现es6Class类_第1张图片

getter和setter

/* super关键字 第一个参数为父类,第二个参数为this指向,
第三个参数为传给父类的属性 */
function _super(Father, _this, args) {
    // 继承父类的属性
    Father.apply(_this, args);
    // 继承父类的方法
    _this.__proto__ = Father.prototype;

}

// _this this指向,attributes修饰的对象属性,fn执行体
function _get(_this, attributes, fn) {
    Object.defineProperty(_this, attributes, {
        get: function() {
            console.log("执行get");
            return fn.call(_this);
        },
    })
}

function _set(_this, attributes, fn) {
    Object.defineProperty(_this, attributes, {
        set: function(newValue) {
            console.log("执行set");
            return fn.call(_this, newValue);
        },
    })
}

// _this this指向,attributes修饰的对象属性,initValue属性值
function _init(_this, attributes, initValue) {
    _this[attributes] = initValue;
    _this["_" + attributes] = initValue;
}

// 父类
function Person() {
    // 初始化属性
    _init(this, "name", arguments[1]);
    _init(this, "age", arguments[2]);
    this.description = "哺乳动物";
    Person.prototype.eat = function() {
        console.log("吃个饭");
    }
}

// 第一个参数为谁的对象,第二个参数为姓名,第三个参数为年龄
function Obj() {
    // 初始化属性
    _init(this, "whoObject", arguments[0]);
    // 设置getter和setter
    /* 第三个参数传入箭头函数也不会出错(因为箭头函数的this指向
    不能改变,且指向定义时的上下文,在这里刚好是我们需要的this) */
    _get(this, "whoObject", function() {
        return this["_whoObject"];
    })

    _set(this, "whoObject", function(newValue) {
        /* 为什么加_whoObject而不使用whoObject,
        因为调用栈溢出,详情查看推荐阅读中的访问器属性 */
        this["_whoObject"] = newValue;
    })
    _super(Person, this, arguments);
    this.__proto__.kiss = function() {
        console.log("亲吻" + this.whoObject);
    }
}

// 没错,帅逼有两个对象,羡慕啊~~
const obj1 = new Obj("帅逼", "zhangsan", 12);
const obj2 = new Obj("帅逼", "lisi", 21);
console.log(obj1); // { name: 'zhangsan', age: 12, description: '哺乳动物', whoObject: '帅逼' }
console.log(obj2); // { name: 'lisi', age: 21, description: '哺乳动物', whoObject: '帅逼' }
obj1.kiss(); // 亲吻帅逼
obj2.kiss(); // 亲吻帅逼
// lisi移情别恋了
obj2.whoObject = "富贵";
console.log(obj2.whoObject);
console.log(obj1.whoObject);
console.log(obj1.eat == obj2.eat); // true

(es5实现es6+5)使用es5来实现es6Class类_第2张图片

私有属性兼最终代码

/* super关键字 第一个参数为父类,第二个参数为this指向,
                                                                                                                                                                                                                        第三个参数为传给父类的属性 */
function _super(Father, _this, args) {
     // 继承父类的属性
     Father.apply(_this, args);
     // 继承父类的方法
     for (const key in Father.prototype) {
         if (Object.hasOwnProperty.call(Father.prototype, key)) {
             const element = Father.prototype[key];
             if (!_this.__proto__[key]) _this.__proto__[key] = element;
         }
     }
 }

 // _this this指向,attributes修饰的对象属性,fn执行体
 function _get(_this, attributes, fn) {
     Object.defineProperty(_this, attributes, {
         get: function() {
             console.log("执行get");
             return fn.call(_this);
         },
     });
 }

 function _set(_this, attributes, fn) {
     Object.defineProperty(_this, attributes, {
         set: function(newValue) {
             console.log("执行set");
             return fn.call(_this, newValue);
         },
     });
 }

 // _this this指向,attributes修饰的对象属性,initValue属性值
 function _init(_this, attributes, initValue) {
     _this[attributes] = initValue;
     _this["_" + attributes] = initValue;
 }

 // 私有属性
 function _private(value) {
     // 使用闭包来实现私有属性
     let obj = {
         Value: value,
         setValue: function(newValue) {
             this.Value = newValue;
         },
     };
     return function() {
         return obj;
     };
 }
 // 父类
 function Person() {
     // 初始化属性不需要定义get和set方法可以直接使用this.name = argument[1];
     _init(this, "name", arguments[1]);
     _init(this, "age", arguments[2]);
     this.description = "哺乳动物";
     Person.prototype.eat = function() {
         console.log("吃个饭");
     };
 }

 // 第一个参数为谁的对象,第二个参数为姓名,第三个参数为年龄,第四个参数为三维
 function Obj() {
     _super(Person, this, arguments);
     // 初始化属性
     _init(this, "whoObject", arguments[0]);
     // 设置getter和setter
     /* 第三个参数传入箭头函数也不会出错(因为箭头函数的this指向
         不能改变,且指向定义时的上下文,在这里刚好是我们需要的this) */
     _get(this, "whoObject", function() {
         return this["_whoObject"];
     });

     _set(this, "whoObject", function(newValue) {
         /* 为什么加_whoObject而不使用whoObject,
                 因为调用栈溢出,详情查看推荐阅读中的访问器属性 */
         this["_whoObject"] = newValue;
     });
     this.__proto__.kiss = function() {
         console.log("亲吻" + this.whoObject);
     };
     // 设置女生的三维是私有属性,只有自己知道
     let threeDimensional = _private(arguments[3])().Value;
     console.log("只有我自己知道" + threeDimensional); // "81 54 86"
 }

 // 没错,帅逼有两个对象,羡慕啊~~
 const obj1 = new Obj("帅逼", "zhangsan", 12, "81 54 86");
 const obj2 = new Obj("帅逼", "lisi", 21, "1 2 3");
 console.log(obj1); // { name: 'zhangsan', age: 12, description: '哺乳动物', whoObject: '帅逼' }
 console.log(obj2); // { name: 'lisi', age: 21, description: '哺乳动物', whoObject: '帅逼' }
 obj1.kiss(); // 亲吻帅逼
 obj2.kiss(); // 亲吻帅逼
 // lisi移情别恋了
 obj2.whoObject = "富贵";
 console.log(obj2.whoObject);
 console.log(obj1.whoObject);
 // zhangsan你的三维是多少?
 console.log(
     obj1.threrDimensional ? obj1.threrDimensional : "三维是秘密我不告诉你"
 );
 console.log(obj1.eat == obj2.eat); // true

(es5实现es6+5)使用es5来实现es6Class类_第3张图片

你可能感兴趣的:(#,es5实现es6+新特性,基础,前端,es6,javascript)