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
/* 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
/* 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