工厂模式
在实际工作中,通常创建对象时,需要附加一些默认的属性或方法,因此:
function createObject(name) {
//可以直接创建对象,也可以做继承。
const obj = {};
//创建完对象,可以对对象做进一步处理
obj.name = name;
return obj;
}
const obj = Object.create('张三');
//详解三种模式
const obja = {
a: function () {
},//分别有各自的指向。
b: aa//同时指向外一个函数
}
function aa() {
}
obja.__proto__.c = function () {
}//给函数添加一个祖先元素。
如果需要为对象附加方法,通常采用如下方式:
function createObject(name) {
//可以直接创建对象,也可以做继承。
const obj = {};
//创建完对象,可以对对象做进一步处理
obj.name = name;
obj.eat = eat;
return obj;
}
function eat(){
}
const obj = createObject('张三');
或者,直接采用构造函数:
function createObject(name) {
this.name = name;
}
createObject.prototype.eat = function () {
}
const obj = new createObject('张三');
通常,为对象附加的函数(方法),都是多个对象只需要共用一个函数就可以,因此,可以将函数附加到对象的原型对象上。
es6 使用class关键字从语法上模拟了真正面向对象的语法。class 实际上是语法糖。
要产生继承,必须有一个模板,
class Stu1 {
constructor() {//构造器函数有且只有一个。
this.name = '';//用this的叫公共变量,没有就是私有变量
this.age = 18;
let a = 1;
//构造器本身是函数,返回值如果不是对象,或没有返回值则不会对结果造成影响。
//但是如果返回值是对象,则返回值的对象会覆盖原有的对象作为new的结果。
return undefined;//不影响
return 123;//不影响
return { xxx: 123 }//会覆盖。
}
eat() {
}//不能加,或 ;分隔符。
sleep() {
}
}
const obj2 = new Stu1();
es6 通过class关键字来定义一个类。
类的定义中有一个constructor函数,这是整个类的构造器。负责初始化对象及接收参数。
constructor中定义属性,使用this.属性名称将属性暴漏。
类的方法不需要function关键字,而且函数之间不能有逗号分隔。
使用new关键字(实例化关键字)将一个类实例化为对象。
继承
class 富一代 {
constructor(value) {
this.money = 99999;
this.value = value;
}
game() {
console.log('高尔夫')
}
// static game() {
// console.log('高尔夫')
// }//静态方法,表示当前方法时当前类的静态方法,不会被继承。
//思聪.game()报错
//富一代.game()可用
}
class 富二代 extends 富一代 {
constructor(name, value) {
super(value);//类似call,调用继承富一代的constructor函数。
//super应该在自身属性定义之前执行。
this.money = 0;//两个思聪都没钱了。
this.name = name;
}
}
class 穷二代 extends 富一代 {
constructor(name, value) {
super(0);//类似call,调用继承富一代的constructor函数。
//super应该在自身属性定义之前执行。
this.money = 0;//两个思聪都没钱了。
this.name = name;
}
game() {
console.log('躺平');
}
}
const 林 = new 富一代();
const 聪 = new 富二代('张三', 123);
//money是私有的,game是公用的,参数被富二代的constructor接受
const 三 = new 穷二代('棒子', 456);
console.log(林);
console.log(林.game());
console.log(聪);
console.log(聪.game());
console.log(三.money);//0
console.log(三.game());//躺平 ,多态
es6使用 extends 来继承。
为了实现继承,实例化时,传入参数首先被子类的 constructor执行,但是,从语法上,应该是主类的 constructor 先执行,因此,引入了 super()方法来调用主类的 constructor。
静态方法和静态属性(扩展)
静态方法,如果为一个类的方法(函数)前增加 static关键字,表示当前方法是当前类的静态方法,不会被继承。
class 富一代 {
constructor() {
}
static game() {
console.log('打高尔夫');
}
}
class 富二代 extends 富一代 {
constructor(name, value) {
super();
}
}
const 思聪 = new 富二代('张三', 123);
思聪.game();//报错
富一代.game();//打高尔夫
es的class中,目前还不能对属性添加静态关键字:
constructor(value) {
static this.money = value;//报错
}
折中的使用如下方法来变相实现静态属性:
class 富一代 {
constructor(value) {
//将this直接替换为class名称
富一代.money = value;
}
}
class 富二代 extends 富一代 {
constructor(name, value) {
super(123);
this.name = name;
}
}
const 思聪 = new 富二代('张三', 123);
console.log(思聪.money);//undefined
console.log(富一代.money);//123
多态
class car {
//构造器
constructor() {
//用this暴漏的变量叫做公共变量,没有的就私有变量
this.name = '';
}
run() {
console.log(this.name + '这辆车开起来了');
}
zhuang() {
console.log(this.name + '这辆车撞人了');
}
}
class myCar extends car {
constructor(n) {
//引用主类的构造器
super()
this.name = n;
}
}
const a = new myCar('兰博基尼');
const b = new myCar('法拉利');
a.run();//兰博基尼这辆车开起来了
b.run();//法拉利这辆车开起来了
不同的对象执行相同的方法,产生不同的结果,这个叫做多态。
虽然run方法定义在主类,但是其内需要使用name属性时,优先查找的却是字类,因为对象是子类实例化的。