js面向对象

192 阅读4分钟

万物皆对象

想要了解自然界 自然界中万事万物都是我们要研究的对象 “对象”:所有要研究和学习操作的都是研究对象。

我们需要把自然界中万事万物 按照其特点划分成不同的类别:

动物类 植物类 微生物类

动物类:人类、哺乳动物、两栖动物、飞行动物

人类:男人类 女人类

类别也不是具体的东西 指的是一个范围 对对象这个抽象的东西 具体化一些

所以我们把某一个事物叫做一个类的实例

实例:类别中的具体事物

那在我们js中,有哪些类呢?

内置类: 【数据类型】

每一种数据类型都有一个自己对应的类别
  •  Number数字类,每一个数字(NaN\Infinity)都是它的一个实例
    
  •  String、Boolean、(Null、Undefined)、(Symbol)、BigInt、Object(Array、RegExp、Date. ..)、Function
    
  •  其中Null、Undefined是受浏览器保护的,不能被我们查看
    
    【每一个DOM元素对象也有自己的类和祖先类】
  •   DIV元素对象 -> HTMLDivElement -> HTMLElement -> Element -> Node -> EventTarget -> Object
    
  •   A元素对象 -> HTMLAnchorElement -> HTMLElement ...
    
  •   document -> HTMLDocument -> Document -> Node ...
    
  •   window -> Window -> WindowProperties -> EventTarget ...
    
  •   元素集合 -> HTMLCollection -> Object
    
  •   节点集合 -> NodeList -> Object
     
     例1:
     数组的学习
      1.准备Array类的一个实例(一个具体的数组)
      2.开始研究数组的结构、研究它的方法(一般都在Array.prototype原型上呢)
       let arr = [10, 20, 30];
     我们在浏览器中console.dir(arr)就可以查看该数组中的属性及方法
    

但是在我们开发过程中,光这些内置类是不够的,我们还需要自己构建一些类“自定义类”来完成功能的开发

创建函数并且把函数执行(每一个类都是函数数据类型的,包含内置类和自定义类)

例如我们typeof Array,typeof String 结果都是function

function func() {}
func();

自定义类(类名的第一个首字母一般都要大写)
function Func() {
 
}
let f = Func(); 把它当做普通函数执行(形成私有的上下文、作用域链、THIS[window]、ARGUMENTS、形参赋值、变量提升、代码执行...),f获取的是函数的返回结果(函数没有RETURN,所以f=undefined)
let f = new Func(); 这是构造函数执行(当做类来执行,而不是当做普通函数了),此时Func被称为“类”,返回的结果(f)被称为“当前类的一个实例”,它是一个实例对象
console.log(f);

举个例子

例1:
构造函数执行(类) 和 普通函数执行 的区别?
function Func(x, y) {
    let num = x + y;
    this.x = x;
    this.y = y;
}
let f1 = Func(10, 20);
/*
    EC(F1)形成私有上下文
        AO(F1)私有变量对象
        作用域链:EC(F1),EC(G)
        初始化this:window
        形参赋值:x=10,y=20
        变量提升:--
        代码执行:let num = x + y;
                  this.x = x;
                  this.y = y;
                  这时时给window添加x,y属性
                  没有return,返回undefined
*/
console.log(f1, window.x); //=>undefined 10

而构造函数执行,大体上与普通函数一样(具备函数执行的一面)

let f2 = new Func(10, 20);
/*
    EC(F1)形成私有上下文
        AO(F1)私有变量对象
        作用域链:EC(F1),EC(G)
          * 和普通函数的区别:
              1.首先创建一个对象(这个对象就是当前类的实例)
              2.让上下文中的this指向这个对象
        初始化this:对象的地址(AAAFFF000)
        形参赋值:x=10,y=20
        变量提升:--
        代码执行:let num = x + y;
                  this.x = x;
                  this.y = y;
                  这时是给当前实例对象添加属性和方法
                  * 没有return,和普通函数的区别:
                    在函数没有返回值的情况下,默认会把创建的实例对象返回,
                    (如果函数中写了return,返回的基本类型值,还是以返回实例为主,返回的是引用类型值,自己编写的返回值会替换默认返回的实例)
*/      
console.log(f2); //=>{x:10,y:20} 当前类的实例对象 

基于 instanceof 可以检测当前对象是否为 某个类 的实例

语法:实例 instanceof 类,是的话返回TRUE,反之FALSE

每一个对象(包含实例对象)都有很多属性和方法,在自己堆内存中存储的都是私有的属性方法,基于__proto__原型链查找类prototype原型上的都是共有的属性方法

检测属性是当前对象私有的还是公有的:

  1. 对象.hasOwnPrototype(属性) 检测是否为私有的属性(只有是私有属性才是TRUE,哪怕有这个属性,但是为公有属性结果也是FALSE)

  2. 属性 in 对象:检测是否为他的属性(不论是公有还是私有都可以)

     console.log('x' in f2); //=>TRUE
    
     console.log(f2.hasOwnProperty('x')); //=>TRUE
      
     console.log('toString' in f2); //=>TRUE
     
     console.log(f2.hasOwnProperty('toString')); //=>FALSE  toString是他的公有属性