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

it2024-11-16  3

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
最新回复(0)