目录
1.遍历
2. 面向过程和面向对象对比
3.类
4.类的继承
5.class静态成员
1.遍历
只要有iterator接口,就可以用 for..of遍历,但是不推荐用来遍历对象。在遍历数组是推荐使用for...of遍历,在遍历对象时推荐使用for...in。
跳出循环的方法:
for | break、continue、return |
for in | break、continue、return |
for of | break、continue、return |
forEach | return |
for...in和for...of的区别:
- for...in是ES5的语法,for...of是ES6新增的语法。
- for...in在遍历时具有顺序不确定性,for...of在遍历时是按照顺序来遍历的。
- for...in遍历的是对象的key值,和数组的序列号,而for...of不可以用来遍历对象,在遍历数组时会把数组的值给遍历出来。
- for...in遍历时会将数组或对象的原型上的属性或者方法给遍历出来,此时可以通过hasOwnProperty()来判断这个属性是否属于自身,或者用Object.keys()方法获取对象键组成的数组,这个数组不包含原型的属性和方法,而for...of只会把当前数组自身的元素值给遍历出来。
- for...of可以用来遍历map集合,for...in不能遍历map集合。
2. 面向过程和面向对象对比
面向过程 | 面向对象 | |
优点 | 性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。 | 易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 |
缺点 | 不易维护、不易复用、不易扩展 | 性能比面向过程低 |
3.类
ES6新增类的概念,在ES5中没有类,一般用构造函数来模拟类的概念。我们可以通过class关键字来定义一个类。下面我们用构造函数和class分别来编写一个类。
javascript"> function Person1(name, age) {
this.name = name;
this.age = age;
}
Person1.prototype.say = function () {
console.log('aaa');
}
let p1 = new Person1('TOM', 14);
class Person2 {
constructor(name, age) {
// constructor用来定义构造函数初始化,通常我们将类的属性写在constructor内。
this.name = name;
this.age = age;
};
say() {
console.log('say');
}
// 等同于在es5中将方法写在函数的原型对象上。
}
let p2 = new Person2('TOM', 14);
console.log(p1, p2);
两者的运行结果是一样的,但类中有一些需要我们注意的地方:
- 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
- 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
- 当不传参时可以不写constructor函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
- 多个函数方法之间不需要添加逗号分隔 ,会报错。可以用分号或者直接不写,都不会报错
- 生成实例 new 不能省略,否则就会报错。
- 语法规范,:创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要
加function
-
必须先声明类再实例化否则会报错,但是再ES5中就不会报错,因为ES5中有函数提升的概念。
-
constructor中的this指向的是new出来的实例对象
4.类的继承
在ES6中,类的继承主要是由extends super两个关键字来完成的。extends来确定继承的是哪个类,super用来确定继承的是父类中的哪些属性和方法。
javascript"> class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
// 原型对象
sum() {
console.log(this.x + this.y);
}
}
// 子继承父 extends
class Son extends Father {
constructor(x, y, z) {
super(x, y); //超级类:实现继承,此时x,y是父类中的x和y,继承语句放在最前面
this.z = z;
}
walk() {
console.log(this.y + 'waking');
}
sum() {
console.log(this.x + this.y + 'son');
// 调用父方法
super.sum();
}
}
let s1 = new Son(10, 20, 21);
注意:
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
- 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,
- super 必须在子类this之前调用。
- 类里面的共有的属性和方法一定要加this使用.
-
自定义的方法,一般也指向的new出来的实例对象
-
绑定事件之后this指向的就是触发事件的事件源
5.class静态成员
类(class)的静态成员是指直接绑定在类本身上而不是类的实例上的属性或方法。静态成员可以通过类名直接访问,而不需要先创建类的实例。在类中使用 static
关键字可以定义静态属性和静态方法。静态属性的值通常是固定的,与类相关联,而不是与类的实例相关联。
javascript">class MathUtils {
static PI = 3.14159; // 静态属性 PI
static square(x) { // 静态方法,计算平方
return x * x;
}
static cube(x) { // 静态方法,计算立方
return x * x * x;
}
}
// 使用静态属性和静态方法
console.log(MathUtils.PI); // 访问静态属性 PI
console.log(MathUtils.square(5)); // 调用静态方法计算 5 的平方,输出结果为 25
console.log(MathUtils.cube(3)); // 调用静态方法计算 3 的立方,输出结果为 27
- 静态属性和静态方法是属于类本身的,而不是类的实例。因此 不需要实例化对象也能访问类的静态方法。
- 子类可以继承父类的静态属性和静态方法。子类可以通过
super
关键字来调用父类的静态方法,或者直接通过类名来访问父类的静态属性和静态方法。 - 与实例方法不同的是,静态方法不能被子类中的同名静态方法覆盖。如果在子类中定义了与父类相同名称的静态方法,实际上是在子类中创建了一个新的静态方法,而不是覆盖父类的静态方法。
- 在静态方法中,不能使用
this
关键字来引用类的实例或实例属性,因为静态方法是属于类本身的,没有实例相关的上下文。如果需要访问实例属性,必须通过参数传递或者在静态方法中直接访问静态属性。