个人自学前端20-JS13-面向对象和继承实现,判断变量是否为数组或纯对象,伪数组

面向对象和继承实现

一 面向对象

面向对象是一种编程的思维,组织程序的一种方式。

面向对象三大特征:

1:封装

2:继承

3:多态 ( js无法实现多态,因为 js 函数没有重载功能 )

面向对象编程入门思路:

1:抽象出类。

抽象类的过程,需要思考,这个类的私有属性和公有方法都有什么。

如果有多个类,还需要实现继承等类之间的关系。

2:实例化。

通过抽象的类实例化对应个数的实例。

熟悉面向对象编程后,你会发现:

面向对象编写的程序几乎没有全局变量。

全局变量或者某些局部变量都变成了类的私有属性。

函数都变成了类的公有方法。

注意,面向对象抽象类的过程,是没有对和错的,只有好和坏。

面向对象编程,需要对 this 的指向问题非常清楚

二 创建自定义类

2.1:创建类。

js 的类都由函数充当。因此自定义类也需要通过一个普通函数来创建。

这个用于创建类的函数叫构造函数,习惯首字母大写。

创建类,需要定义类的私有属性和公有方法。

// 构造函数创建类的私有属性。
function Person(name){
	this.name = name
}
// 类的原型创建公有方法。
Person.prototype.speak = function(){
    console.log(this.name);
}

2.2:实例化

有了类之后,就可以通过类来实例化了。实例化需要通过操作符 New 修饰。

let oYm = new Person('幂幂');
// 访问私有属性.
console.log(oYm.name); // 幂幂
// 调用公有方法.
oYm.speak(); // 幂幂

2.3:new 做的事情

函数调用前有new:

1:让函数内的 this 指向类实例。

2:让类实例默认继承类的原型。

3:让构造函数返回类实例。

三 继承

js 的类继承,可以通过两方面完成。

1:如何继承私有属性。

2:如何继承公有方法。

3.1 继承私有属性

可以通过在子类中调用父类构造函数,并且通过call来改变this指向子类实例的方法来继承父类私有属性。

// 父类Person
function Person(name){
	this.name = name
}
// 子类Student
function Student(number,name){
    // 继承父类私有属性
    Person.call(this,name);
	this.num = number
}

3.2 继承公有方法

要继承父类的公有方法,必须让父类原型的公有方法出现在子类的原型链上.

或者让父类的原型对象出现在子类的原型链上.

可行的方法是: 让子类原型赋值为父类空实例.

// 父类Person
function Person(name){
	this.name = name
}
// 子类Student
function Student(number,name){
    // 继承父类私有属性
    Person.call(this,name);
	this.num = number
}
// 继续公有方法.子类实例继承子类原型,赋值后等同于继承父类实例,
Student.prototype = new Person();

这个做法可行,但是需要额外调用一次父类构造函数。不太好。

// 通过这个方法,可以让子类原型默认继承父类原型。
Student.prototype = Object.create(Person.prototype);

面试常问 js 的继承问题,可以通过这两方面回调。

同时继承私有属性和公有方法的继承方式称之为混合继承。派生的方法有寄生继承。

3.3 一些检测方法

访问对象的上一级原型对象:

对象.__proto__
Object.getPrototypeOf(对象)

修改对象的上一级原型对象:

对象.__proto__ = 新的对象
Object.setPrototypeOf(对象,新的对象)

检测对象是否具有某个属性.

对象.hasOwnProperty(属性)

检测属性是否存在于对象的原型链上

属性 in 对象

检测A对象是否存在于B对象的原型链上.

A对象.isPrototypeOf(B对象)

检测类的原型是否存在于对象的原型链上

对象 instanceof 类
instanceof 和 isPrototypeOf的区别
instanceof检测类的原型对象在不在原型链上
isPrototypeOf检测任意的对象在不在原型链上.

四 其他

4.1 数组的方法

实例方法
push,pop,shift,unshift,reverse,sort,splice
concat,slice,includes,indexOf,join
forEach,map,filter,some,every,reduce,find,findIndex

静态方法
Array.isArray => 判断是不是数组.
Array.from => 把伪数组转换为真正的数组.
Array.of => 代替数组的构造函数.

4.2 如何判断一个变量是不是数组?

1.不能用typeof,因为typeof得到的结果是object
2.用Array.isArray在IE8不支持.
3.intanceof 也不一定准确.

    let arr = [];

	// let flag1 = isArray(arr);
    // let flag2 = isPlainObject({});

    // 封装一个函数用于判断一个变量是不是数组.
    function isArray(arr) {
      return Object.prototype.toString.call(arr) === '[object Array]'
    }

	// 100%正确的答案
    // if (Object.prototype.toString.call(arr) === '[object Array]') {
    //   alert('是数组')
    // } else {
    //   alert('不是数组')
    // }

4.3 如何判断一个变量是不是纯对象?

不能用typeof,为数组,null和纯对象的typeof结果都是object.

    // 封装一个函数用于判断一个变量是不是纯对象.
    function isPlainObject(obj) {
      return Object.prototype.toString.call(obj) === '[object Object]'
    }

4.4 伪数组

    let aDiv = document.querySelectorAll('div');

    // aDiv不是数组实例,因此不能用数组的方法。
    // 但是aDiv可以使用下标,可以有length属性表示元素个数.

    // aDiv是一种伪数组.可以有下标,可以有length.但是就是不能访问数组的方法.
    // 所有的标签数组都是伪数组.
    // arguments也是一种伪数组.(ES6的rest参数是一个真正的数组).
    // fileList也是一个伪数组.

    console.log(Array.isArray(aDiv));
    console.log(aDiv instanceof Array);
    console.log(Array.prototype.isPrototypeOf (aDiv));
    console.log(Object.prototype.toString.call(aDiv) === '[object Array]');

    function fn(...rest) {
      console.log(Array.isArray(rest));// true
      console.log(Array.isArray(arguments));// false
    }

    fn();
posted @ 2021-07-31 10:49  暗鸦08  阅读(91)  评论(0)    收藏  举报