<script>
/*
什么是类:
在ES6中新增加了类的概念,可以使用class关键字声明一个类,
之后以这个类来实例化对象。类抽象了对象的公共部分,它泛指
某一大类( class )对象特指某一个,通过类实例化一个具体的对象
表面看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然
是原型和构造函数的概念。
所以他也是构造函数的——语法糖
*/
//一、类定义---------------------------------------------------------------------------------------------
/* //1. 匿名类
let Example = class {};
//2.命名类
let Example = class Example {};
//3.类声明
class Example {}
//不可以重复声明一样的名字 */
// class Star1 {}
// var star1 = new Star1();
//二、类不会被提身-----------------------------------------------------------------------------------------
// class Example {}
// let wq = new Example();
// let star = new Start();
// function Start(uname, age) {
// this.uname = uname;
// this.age = age;
// }
//跟构造函数作比较
// let star = new Star();
// function Star() {}
//三、创建类和添加方法-------------------------------------------------------------------------------------
/*
知识要点:
1.类constructor构造函数:
constructor()方法是类的构造函数(默认方法),用于传递参数返回实例对象,
通过new命令生成对象实例时,自动调用该方法。如果没有显示定义,类内部会自动给拽们创建一个constructor
2.总结要点
(1) 通过class 关键字创建类,类名我们还是习惯性定义首字母大写
(2) 类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象
(3) constructor函数只要new生成实例时,就会自动调用这个函数,如果我们不写这个函数,类也会自动生成这个函数
(4) 生成实例 new 不能省略(这个new干了些啥)
1.在内存中创建了一个新对象
2.这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性
3.构造函数内部的this被赋值为了这个新对象(即this指向新对象)
4.执行构造函数内部的代码(给新对象添加属性)
5.如果构造函数返回非空对象,则返回该对象:否则,返回刚创建的新对象
(5) 最后注意语法规范,创建类,类名后面不要加小括号,生成实例类名后面加小括号,构造函数不需要加function
(6) 我们类里面所有的函数不需要写function
(7) 多个函数方法之间不需要添加逗号分隔
*/
/* class Sxample {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
show(money) {
console.log(this.uname + money);
}
artistic(talent) {
console.log(this.uname + talent);
}
}
var example1 = new Sxample("王总", 18);
var example2 = new Sxample("王老板", 28);
// console.log(example1.uname, example1.age);
// console.log(example2.uname, example2.age);
example1.show("很有钱");
example2.artistic("很有钱"); */
//四、(extends、super)类的继承---------------------------------------------------------------------------------
/*
知识要点:
1.
如果在基础父类的情况下还下下面的语句,这son传的参数给了子类的
x和y的值,而父类却没有,如果想把子类的x和y传给父类的话则需要使用到super关键字了
2.
super关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数
3.
// 继承中的属性或者方法查找原则:就近原则
// 1.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
// 2.继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就进原则)
n
**使用super时要注意几个问题
1.super()只能在子类构造函数和静态方法内使用
2.不能单独引用super()关键字,要么用它调用构造函数,要么用它引用静态方法 **
3.调用super()会调用父类构造函数,并将返回实例赋值给this **
4.super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入
5.如果没有定义类构造函数,在实例化派生类时会调用super(),而且会传入所有传给子类的参数
6.在类构造函数中,不能调用super()之前引用this **
7.如果在子类中显示定义了构造函数,则要么必须在在其中调用super(),要么必须在其中返回一个对象
*/
//1.extends
/* class Father {
constructor() {}
money() {
console.log(10000 + "元");
}
}
class Son extends Father {
money1() {
console.log(100 + "元");
}
}
var son = new Son();
son.money(); */
//2.super调用父类的构造函数
/* class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father {
constructor(x, y) {
super(x, y);
}
}
var son = new Son(1, 2);
son.sum(); */
/* function Star(uname, age) {
this.uname = uname;
this.age = age;
// this.show = function () {
// console.log("我是里面的方法");
// };
}
Star.prototype.show = function () {
console.log("我是原型链");
};
var star = new Star(1, 2); //----对象1
var star1 = new Star(2, 3); //----对象2
star.show();
star1.show();
console.log(star.show === star1.show);
console.log(star.__proto__ === star1.__proto__);
class Fun {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
show() {
console.log("我是类方法");
}
}
var fun = new Fun(1, 2);
var fun1 = new Fun(2, 3);
fun.show();
fun1.show();
console.log(fun.show === fun1.show);
// Fun.prototype.show = function () {
// console.log("我是类方法");
// }; */
//3.super调用父类的普通函数
/* class Father {
constructor(uname) {
this.uname = uname;
}
say() {
return "我是爸爸";
}
}
class Son extends Father {
constructor(uname) {
super(uname);
}
say() {
console.log("我是儿子");
console.log(super.say() + "的儿子" + this.uname);
}
}
var son = new Son("张三");
son.say(); */
//五、子类继承父类方法同时扩展自己的方法-----------------------------------------------------------------------
// 父类有加法方法
/* class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y); //8
}
}
// 子类继承父类加法方法 同时 扩展减法方法
class Son extends Father {
constructor(x, y) {
// 利用 super 调用父类的构造函数
// super 必须在子类this之前调用 但也可以省略掉this的操作
super(x, y);
this.x = x;
this.y = y;
}
subtract() {
console.log(this.x - this.y); //2
}
}
var son = new Son(5, 3);
son.sum();
son.subtract(); */
//六、类遵循严格模式-------------------------------------------------------------------------------------------
/*
知识要点:
什么是严格模式:
JavaScript除了提供正常模式外,还提供了严格模式。ES5的严格模式是采用具有限制性
JavaScript变体的一种方式,即在严格的条件下运行的JS代码
严格模式在IE10以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略
怎么开启严格模式:
【为函数开启严格模式】两种情况
一、为脚本开启严格模式
为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 "use strict";(或 'use strict';)
二、为函数开启严格模式
要给某个函数开启严格模式,需要把 "use strict";(或 'use strict';)声明放在函数体所有语句之前
*/
// function fn() {
// "use strict";
// console.log(this);
// }
// fn();
// class Star {
// show() {
// function uname() {
// console.log(this);
// }
// uname();
// }
// }
// var star = new Star();
// star.show();
//七、类的静态属性---------------------------------------------------------------------------------------
/*
知识要点:
构造函数的静态成员和实例成员
静态成员:在构造函数本上添加的成员称为静态成员,只能由构造函数本身访问
静态成员 在构造函数本身上添加成员
静态成员 只能通过构造函数来访问
实例成员:在构造函数内部创建对象成员称为实例成员,只能由实例化的对象来访问
实例成员就是构造函数内部通过this添加的成员 uname、age、sing 就是实例成员
实例成员只能通过实例化的对象来访问
类里面的静态属性——[static]
class本身的属性,即直接定义在类内部的属性(Class.propname),不需要实例化。 ES6 中规定,Class 内部只有静态方法,没有静态属性。
*/
//1.构造函数里的静态成员和实例成员
/* function Star(uname, age) {
this.uname = uname;
this.age = age;
// this.show = function () {
// console.log("我是实例成员");
// };
}
var star = new Star("王总", 18);
console.log(star.uname);
console.log(Star.uname); //实例成员不可以通过构造函数来访问
// star.show();
Star.sex = "男";
console.log(star.sex); //静态成员不可以通过对象来访问
console.log(Star.sex);
Star.prototype.show = function () {
console.log("我是通过原型的方法");
};
star.show();
star.__proto__.show = function () {
console.log("我是方法");
};
star.show();
console.log(star); */
//2.类里面的静态
/* class Star {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
show() {
console.log("我原型对象是" + this.uname);
}
static sing(uname) {
console.log("我原型对象是" + uname);
}
}
var star = new Star("王总", 18);
var star1 = new Star("王老板");
star.show();
Star.sing("王老板"); */
//3.子类的静态方法能够通过super来调用父类的静态方法
/* class Person {
static getName() {
return "lear";
}
}
class Student extends Person {
static getName2() {
return super.getName() + ",hi";
}
}
console.log(Student.getName2()); */
//八、把类当成一个特殊函数,类的是返回对象-----------------------------------------------------------------------
/*
知识要点:
ECMAScript中没有正式的类这个类型
*/
// 1.通过typeof操作符检测类标识符,表明它是一个函数
// class Person {}
// console.log(Person);
// console.log(typeof Person); //function
// 2.类标识有prototype属性,而这个原型也有一个constructor属性指向类自身
// class Person1 {}
// console.log(Person1.prototype);
// console.log(Person1 === Person1.prototype.constructor);
// 3.与普通函数一样,可以使用instanceof操作符检查构造函数原型是否存在于实例的原型链中
/* class Person2 {}
var p = new Person2();
console.log(p instanceof Person2); */
/*
4.由此可知,可以使用instanceof操作符检查一个对象与构造函数,以确定这个对象是不是类的实例。只不过此时
的构造函数要使用标识符,比如前面的例子中要检查p和Person2
如前所述,类本身具有与普通构函数一样的行为,在类的上下文中.类本身在使用new调用时就会被当成构造函数。
重点在于,类中定义的 constructor 方法【不会】被当成构造函数,在对它使用instanceof操作符时会返回false。
但是,如果在创建实例时直接将类构造函数当成普通构造函数来使用,那么instanceof操作符的返回值会返回ture
*/
/* class Person3 {}
var p3 = new Person3();
console.log(p3.constructor === Person3);
console.log(p3 instanceof Person3);
console.log(p3 instanceof Person3.constructor);
var p4 = new Person3.constructor();
console.log(p4.constructor === Person3);
console.log(p4 instanceof Person3);
console.log(p4 instanceof Person3.constructor); */
// 九、实例化对象共享原型对象------------------------------------------------------------------------------------
// 构造函数共享
/* function Person(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function () {
console.log("我在里面创建");
};
}
var wz = new Person("王总", 18);
var zh = new Person("张总", 28);
wz.sing();
zh.sing();
console.log(wz.sing === zh.sing); */
// 类的共享
/* class Example {
constructor(a, b) {
this.a = a;
this.b = b;
}
sum() {
return this.a + this.b;
}
}
Example.prototype.sub = function () {
console.log("我是原型对象");
};
let exam1 = new Example(2, 1);
let exam2 = new Example(3, 1);
console.log(exam1.sum === exam2.sum);
console.log(exam1.sub === exam2.sub);
// 类的所有实例共享一个原型对象。
console.log(exam1.__pro__ === exam2.__pro__); */
// 十、类是一个块级作用域(补充一下)
/* {
function fn() {
console.log("我可以被外面给获取到");
}
class Star {
show() {
console.log("我不能被我们给获取到");
}
}
}
fn();
var star = new Star();
star.Star(); */
</script>