JavaScript高级手记(面向对象、原型、原型链)

本文深入探讨JavaScript中的面向对象编程(OOP)概念,包括类、实例和对象的基本原理。同时,详细解析了原型和原型链的工作机制,帮助读者理解如何在JavaScript中实现和使用这些核心特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript高级手记(面向对象、原型、原型链)

----------面向对象编程--------------


 * OOP (Object Oriented Programming): 面向对象编程
      + java
      + javascript
      + c#
      + python
      + ...
 * POP (Procedure Oriented Programming): 面向过程编程
      + c
      + ...

  =====================================================

  * 面向对象编程语言中的三大概念
      + 对象:泛指(万物皆对象)
      + 类:对象的细分
      + 实例:某一个类别中具体的事物

    JS本身是面向对象编程的:JS这门语言的创建过程就是按照类和实例来创建的,JS有很多的类

    数组类:Array(内置类)
      + 每一个数组都是它的实例
      + 每一个实例都是独立的个体,又自己私有的,也有一些Array提供给每一个实例的公共属性和方法
    
    数据类型类:见到的数据值都是其所属类的一个实例
      + Number
      + String
      + Boolean
      + Symbol
      + BigInt
      + Object
        + Object
        + Array
        + Date
        + RegExp
        + ...
      + Function

    DOM对象/节点或元素集合/样式对象或者集合等
      + HTMLDivElement/ HTMLAnchorElement/ HTMLUListElement ... 每一种元素对象都有一个自己的所属类
      + HTMLElement/ XMLElement ...
      + ELement/ Text/ Document ...
      + Node  节点类
      + EventTarget
      + Object
      + HTMLCollection(通过document.getElementByTagName('*')获取)/ NodeList(通过 document.querySelectorAll('*')获取) ...
      + CSSStyleDeclaration(样式类)
      + ......


  --------------------------------------------------------

* 学习JS基础知识,尤其是API层面的
      +.prototype:存放的是给当前类的实例调用的公共属性和方法
      +.xxx:把其当做对象设定的静态私有属性或方法
      + ...
    
    document.getElementById(ID)
      + 获取上下文只能是 document?
      + getElementById是在Document类原型上提供的方法,所以只有Document的实例才可以调用(document是它的实例)

    [context].getElementByTagName(Tag)
      + Element类的原型上提供getElementByTagName方法
      + 每一个元素标签都是Element类的实例
      + Document的原型上也有这个方法,所以document也可以调用
      + ...

 function sum(x, y) {
  let total = x + y;
  this.total = total;
  console.log(this)
  return total;
}
// let res = sum(10, 20); // window
// console.log(res); // 30

let res = new sum(10,20); // {total: 30} 
console.log(res);  // {total: 30} */
// new 执行:sum不再称为函数,而叫做构造函数或者类(自定义类),处理过程中创建的对象,是当前类的一个实例

/* 
 * new 函数执行:
    + 形成一个私有上下文
    + 创建一个对象(这个对象是当前类的一个实例)
    + 初始化作用域链
    + 初始化this指向:让this指向创建的这个对象
    + 形参赋值
    + 变量提升
    + 代码执行
      代码执行中遇到的 this.xxx = xxx 都是给创建的对象设置私有的属性或方法
      如果没有没有写 return 或者 return 的是一个基本类型值,则返回的是创建的这个对象;如果 return 的是引用类型值,则以返回的值为主
*/

// ================== 分界线 =======================

// 内置类:首字母大写,所以自己创建的类的首字母也会大写
// 所有的类都是一个函数类型值(构造函数):内置类/ 自定义类
 function Fn(x, y) {
  let str = "自定义类";
  this.total = x + y;
  this.say = function(){
    console.log('OK');
  };
}
let f1 = new Fn(10,20);
console.log(f1.total);  // 30
console.log(f1.say);   // 函数
console.log(f1.str);   // undefined str是上下文中的私有变量,跟实例没有关系

let f2 = new Fn; // 这样Fn也和上面的 Fn(10,20) 一样执行了,只是没有传实参而已

console.log(f1 === f2); // false 每一次new类创建的实例都是“独立的实例对象”,new类的实例也称为“构造函数模式” 

  + new Fn();  带参数列表的new   优先级19
  + new Fn;  不带参数列表的new   优先级18
  相同点:最后Fn都会执行,也都会创建Fn类的实例
  区别:是否传参,以及运算优先级不一样(带参数列表的高于不带参数列表的)

-----------------面向对象之原型和原型链------------------

function Fn(){
  this.x = 100;
  this.y = 200;
  this.getX = function(){
    console.log(this.x);
  }
}
// 在原型上扩展公用方法
Fn.prototype.getX = function(){
  console.log(this.x);
}
Fn.prototype.getY = function(){
  console.log(this.y);
};
let f1 = new Fn;
let f2 = new Fn;
console.log(f1.getX === f2.getX); // false
console.log(f1.getY === f2.getY); // true
console.log(f1.__proto__.getY === Fn.prototype.getY); // true
console.log(f1.__proto__.getX === f2.getX);  // false
console.log(f1.getX === Fn.prototype.getX);  // false
console.log(f1.constructor);  // Fn
console.log(Fn.prototype.__proto__.constructor); //Object
f1.getX(); // 100  this=> f1
f1.__proto__.getX(); // undefined  this=> f1.__proto__
f2.getY(); // 200
Fn.prototype.getY(); // undefined  this=> Fn.prototype */
 *  所有的类都是函数类型的(内置类、自定义类)

    所有的函数都天生自带一个属性:prototype(原型,也叫显示原型)
      + prototype的属性值默认是一个对象类型值【堆】
      + 对象中存储的是供实例调用的公共属性和方法
      + 并且在prototype对象上,默认有一个属性:constructor(构造函数),属性值是当前类本身

    所有的对象数据类型值也天生自带一个属性:__proto__(原型链,也叫隐式原型)
      + __proto__属性的值:当前实例所属类的prototype(原型)
      + 哪些值是对象数据类型值:
      + 普通对象、数组对象、日期对象、正则对象...
      + 类的原型 prototype
      + 大部分实例对象(除基本数据类型外)
      + 函数也是对象
 * 如果不知道某个对象是通过哪个类new出来的,那就统一看成是通过Object内置类new出来的,将将该对象看成是Object的一个实例

 * Object是所有对象数据类型的“基类”,Object.prototype也是一个类,但是不知道是哪个具体类new出来的,所以看做是Object的实例,但是Object.prototype.__proto__ 指向自己没有意义,所以 Object.prototype.__proto__ 的值为 null
 function fun() {
  this.a = 0;
  this.b = function(){
    alert(this.a);
  }
}
fun.prototype = {
  b: function(){
    this.a = 20;
    alert(this.a);
  },
  c: function(){
    this.a = 30;
    alert(this.a);
  }
}
var my_fun = new fun();
my_fun.b(); // '0'
my_fun.c(); // '30' */

 my_fun.c() 执行:
  先看一下自己私有的里面有没有函数 c,如果没有就沿着 __proto__ 往原型链上查找,my_fun.__proto__ 值为 fun.prototype, 在这里找到了函数 c,执行该函数,此时函数中的this指向的是实例 my_fun,
  => this.a  === my_fun.a => 30


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值