ES6类和对象
- 在ES6之前如果定义一个类?
- 通过构造函数来定义一个类
- 在ES6之前定义类就是构造函数,静态属性和静态方法是类名.xxx,这种格式,实例方法和属性都放在构造函数内
function Person(myName, myAge) {
// 实例属性
// this.name = "lnj";
// this.age = 34;
this.name = myName;
this.age = myAge;
// 实例方法
this.say = function () {
console.log(this.name, this.age);
}
// 静态属性
Person.num = 666;
// 静态方法
Person.run = function () {
console.log("run");
}
}
- 从ES6开始系统提供了一个名称叫做class的关键字, 这个关键字就是专门用于定义类的
class
- 当我们通过new创建对象的时候, 系统会自动调用
constructor - 创建对象还是 newClassName()
- 静态方法和函数在类里面使用
static关键字,使用的时候,还是ClassName.属性或者ClassName.方法名 ,就行
class Person{
// 当我们通过new创建对象的时候, 系统会自动调用constructor
// constructor我们称之为构造函数
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
}
// 实例属性
// name = "lnj";
// age = 34;
// 实例方法
say(){
console.log(this.name, this.age);
}
// 静态属性
static num = 666;
// 静态方法
static run() {
console.log("run");
}
}
注意点
- 在ES6中,static num = 666;定义"静态属性"的方式并不是ES6正式版标准中的写法, 大部分的浏览器不支持,在ES标准中static只支持定义静态方法不支持定义静态变量,上面的代码,在火狐浏览器中会报错,要定义静态属性,看下面代码
// 静态属性
Person.num = 666;
- 定义类,在ES6标准中添加实例属性都需要在
constructor中添加,以下定义"实例属性"的方式并不是ES6正式版标准中的写法, 大部分的浏览器不支持
class Person{
// 以下定义"实例属性"的方式并不是ES6正式版标准中的写法, 大部分的浏览器不支持
// 实例属性
name = "lnj";
age = 34;
// 实例方法
say(){
console.log(this.name, this.age);
}
}
let p = new Person();
console.log(p);
//ES6正式版本,添加实例属性
class Person{
// 以下定义"实例属性"的方式并不是ES6正式版标准中的写法, 大部分的浏览器不支持
// 实例属性
constructor(){
this.name = "lnj";
this.age = 34;
}
// 实例方法
say(){
console.log(this.name, this.age);
}
}
- ES6之前,定义函数和属性
//往对象里面
function Person(myName, myAge) {
// 实例属性
this.name = myName;
this.age = myAge;
// 实例方法
this.hi = function () {
console.log("hi");
}
}
//往原类里面添加属性
Person.run = function () {
console.log("run");
}
- ES6标准语法里,给类添加方法和属性都得写在
constructor里面,要给原类添加方法,写在类里面就行
class Person{
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
this.hi = function () {
console.log("hi");
}
}
run(){
console.log("run");
}
}
let p = new Person();
console.log(p); //打印出来的,run就在Person的原类里面
- ES6标准语法里,如果通过class定义类, 那么不能自定义这个类的原型对象,给原型对象添加属性和方法,只有一个,只能动态的添加属性和方法,不能给对象自定义原型对象
class Person{
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
this.hi = function () {
console.log("hi");
}
}
run(){
console.log("run");
}
}
let obj = {
constructor: Person,
type: "人",
say: function () {
console.log(this.name, this.age);
}
};
Person.prototype = obj;
let p = new Person();
console.log(p);
1.png
从上面打印结果可以看出,Person对象里面的
__proto__原型对象里面没有obj里面的实例和方法。
- 动态的添加属性和方法
class Person{
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
this.hi = function () {
console.log("hi");
}
}
run(){
console.log("run");
}
}
Person.prototype.type = "人";
Person.prototype.say = function () {
console.log(this.name, this.age);
};
Person.prototype = obj;
let p = new Person();
console.log(p);
2.png
可以看出Person对象里面的
__proto__原型对象里面有属性type和方法say。
继承
- ES6之前的继承
- 在子类中通过call/apply方法借助父类的构造函数
- 将子类的原型对象设置为父类的实例对象
function Person(myName, myAge) {
this.name = myName;
this.age = myAge;
}
Person.prototype.say = function () {
console.log(this.name, this.age);
}
function Student(myName, myAge, myScore) {
// 1.在子类中通过call/apply方法借助父类的构造函数
Person.call(this, myName, myAge);
this.score = myScore;
this.study = function () {
console.log("day day up");
}
// 2.将子类的原型对象设置为父类的实例对象
Student.prototype = new Person();
Student.prototype.constructor = Student;
let stu = new Student("zs", 18, 99);
stu.say();
- 在ES6中如何继承 --->
extends
- 在子类后面添加
extends并指定父类的名称 - 在子类的constructor构造函数中通过
super方法借助父类的构造函数
class Person{
constructor(myName, myAge){
// this = stu;
this.name = myName; // stu.name = myName;
this.age = myAge; // stu.age = myAge;
}
say(){
console.log(this.name, this.age);
}
}
// 以下代码的含义: 告诉浏览器将来Student这个类需要继承于Person这个类
class Student extends Person{
constructor(myName, myAge, myScore){
// 1.在子类中通过call/apply方法借助父类的构造函数
// Person.call(this, myName, myAge);
super(myName, myAge);
this.score = myScore;
}
study(){
console.log("day day up");
}
}
let stu = new Student("zs", 18, 98);
stu.say();
获取对象类型
-
type of输出的都是object
let obj = new Object();
console.log(typeof obj); // object
let arr = new Array();
console.log(typeof arr); // object
function Person() {
// let obj = new Object();
// let this = obj;
this.name = "lnj";
this.age = 34;
this.say = function () {
console.log(this.name, this.age);
}
// return this;
}
let p = new Person();
console.log(typeof p); // object
为啥p输出的也是object呢?因为new Person();的时候,Person()类内部
-
先定义let obj = new Object();
-
再定义 let this = obj;
-
赋值
-
return this;
-
所以打印出来的类型就是object
-
constructor有一个name属性
let arr = new Array();
console.log(arr.constructor.name); // Array
3.png
实例对象里面没有constructor属性,就去原型对象里面找,constructor属性指向类的构造函数,有一个name属性,就可以打印出来其类型了。
console.log(p.constructor.name); // Person
instanceof关键字
- 什么是
instanceof关键字?
instanceof用于判断 "对象" 是否是指定构造函数的 "实例"
class Person {
name = "lnj"
}
let person = new Person()
console.log(person instanceof Person); //true
class Cat {
name = "mm"
}
let c = new Cat();
console.log(c instanceof Person); // false
- instanceof注意点
- 只要指定的构造函数的原型对象出现在实例对象的原型链中都会返回true
function Person(myName) {
this.name = myName;
}
function Student(myName, myScore) {
Person.call(this, myName);
this.score = myScore;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
let stu = new Student();
console.log(stu instanceof Person); // true
内存图.png
看图说逻辑
stu实例对象的原型对象--->Person的实例对象,它的原型对象-------->Person的原型对象,在同一条原型链上,所以返回true
isPrototypeOf属性
- 什么是isPrototypeOf属性
- isPrototypeOf用于判断 一个对象是否是另一个对象的原型
class Person{
name = "lnj";
}
let p = new Person();
console.log(Person.prototype.isPrototypeOf(p)); // true
class Cat{
name = "mm";
}
//Cat是p的原型吗?不是
console.log(Cat.prototype.isPrototypeOf(p)); // false
注意点
function Person(myName) {
this.name = myName;
}
function Student(myName, myScore) {
Person.call(this, myName);
this.score = myScore;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
let stu = new Student();
console.log(Person.prototype.isPrototypeOf(stu)); // true
请看内存图.png的逻辑关系,stu的原型对象跟Person的原型对象,在同一条链上。
判断某个对象是否有某个属性
- 判断某个对象是否有某个属性,不但是类,还有类的原型对象,关键字
in
- in的特点: 只要类中或者原型对象中有, 就会返回true
- in不但可以判断实例对象,还可以去元类里面查找
格式
"key名" in 实例对象;
class Person{
name = null;
age = 0;
}
Person.prototype.height = 0;
console.log("name" in p); // true
console.log("width" in p); // false
console.log("height" in p); // true
- 去类中查找,不去元类里面查找,关键字
hasOwnProperty
- 只会去类中查找有没有, 不会去原型对象中查找
class Person{
name = null;
age = 0;
}
Person.prototype.height = 0;
console.log(p.hasOwnProperty("name")); // true
console.log(p.hasOwnProperty("height")); // false
对象增删改查
- 增、改、查
class Person{}
let p = new Person()
//增
p.name = 'zs';
p["name"] = 'ls';
//改
p.name = 'ww';
p["name"] = 'lk';
//查
p.name = 'haha';
p["name"] = 'hehei';
- 删除
delete p.name;
delete p["name"];
对象遍历
- 在JavaScript中对象和数组一样是可以遍历的
- 什么是对象的遍历?
- 对象的遍历就是依次取出对象中所有的属性和方法
- 如何遍历一个对象?
- 在JS中可以通过高级for循环来遍历对象
- 以下代码的含义: 将指定对象中所有的属性和方法的名称取出来了依次的赋值给key这个变量
for(let key in obj){}
注意点
- ES6定义类的格式, 会将方法默认放到原型对象中,ES6之前定义的,不会将方法放到原型对象中
class Person{
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
}
// 注意点: ES6定义类的格式, 会将方法默认放到原型对象中
say(){
console.log(this.name, this.age);
}
}
let p = new Person("LNJ", 34);
console.log(p);
- 取值的时候,注意点
- 以下代码的含义取出p对象中名称叫做当前遍历到的名称的属性或者方法的取值
p[key] //相当于p["name"] / p["age"] / p["say"]
- 以下代码的含义取出p对象中名称叫做key的属性的取值
p.key
function Person(myName, myAge){
this.name = myName;
this.age = myAge;
this.say = function(){
console.log(this.name, this.age);
}
}
let p = new Person("LNJ", 34);
console.log(p);
for(let key in p){
if(p[key] instanceof Function){
continue;
}
// console.log(key); // name / age / say
// 注意点: 以下代码的含义取出p对象中名称叫做当前遍历到的名称的属性或者方法的取值
console.log(p[key]); // p["name"] / p["age"] / p["say"]
// 注意点: 以下代码的含义取出p对象中名称叫做key的属性的取值
// console.log(p.key); // undefined
}
对象解构赋值
1.在数组的解构赋值中, 等号左边的格式必须和等号右边的格式一模一样, 才能完全解构
let [a, b, c] = [1, 3, 5];
console.log(a, b, c); // 1 3 5
- 在数组的解构赋值中, 两边的个数可以不一样
let [a, b] = [1, 3, 5];
console.log(a, b); // 1 3
let [a, b, c] = [1, 3];
console.log(a, b, c); // 1 3 undefined
- 在数组的解构赋值中,如果右边少于左边, 我们可以给左边指定默认值
let [a, b, c = 666] = [1, 3];
console.log(a, b, c); // 1 3 666
- 对象的结构赋值
2.1 在对象的解构赋值中, 等号左边的格式和字段必须和等号右边的格式一模一样, 才能完全解构
let obj = {
name: "lnj",
age: 34
}
let {name, age} = obj;
console.log(name, age);
2.2 在对象的解构赋值中, 两边的个数可以不一样,但是key名必须一模一样
let obj = {
name: "lnj",
age: 34,
height:18
}
let {name, age} = obj;
console.log(name, age);
2.3 在对象的解构赋值中,左边的值只有一个,key完全对,那么只会查找这个key的值,其他的不查
let {age} = {name: "lnj",age: 34};
console.log(age); // 34
注意点: 在对象解构赋值中, 左边的变量名称必须和对象的属性名称一致, 才能解构出数据







网友评论