JS面向对象编程学习

面向对象编程

JS 中的 this

js 复制代码
function f() {
	console.info(this.x);
}
var obj = {
	f: f,
	x: 1,
};
var x = 2;
f(); // 2
obj.f(); // 1

/* ************** */
let foo = function () {
	var self = this;
	console.info(this === obj);
	f();

	function f() {
		console.info(this === obj);
		console.info(self === obj);
		console.info(self);
	}
};

var obj = {
	m: foo,
};

obj.m();
// true
// false
// true
  • this 的指向
    • 全局作用域的 this 指向 window || global(node 中) 对象
    • 函数中的 this 指向调用该函数的对象
    • 对象方法中的 this 指向调用该方法的对象
js 复制代码
const obj = {
	name: "aa",
	sayName: function () {
		console.log(this.name);
	},
};
obj.sayName(); // aa
  • 构造函数中的 this 指向新创建的对象
js 复制代码
function Person(name) {
	this.name = name;
}

const alice = new Person("Alice"); // alice.name = "Alice"
console.info(alice.name); // Alice
  • 箭头函数中的 this 不会创建新的 this 上下文,而是捕获外层作用域的 this
js 复制代码
const obj = {
	name: "Fa-ce",
	sayName: () => {
		console.log(this.name);
	},
};

obj.sayName(); // undefined

this.name = "Fa-ce1";
obj.sayName(); // Fa-ce1
  • 事件处理函数中的 this 通常指向触发元素的对象
js 复制代码
// DOM 事件 浏览器环境执行
const body = document.querySelector("body");
const div = document.createElement("div");
div.id = "myDiv";
body.appendChild(div);
document.getElementById("myDiv").addEventListener("click", function () {
	console.info(this);
});
div.click(); //  <div id="myDiv"></div>

/* ****** JS 函数 ******** */

function sayHello() {
	console.log(this);
}
sayHello(); // window(非严格模式) || undefined(严格模式) || global(node 中)
  • 如何改变 this 的指向 call、apply、bind
js 复制代码
function greet(greeting, xxx) {
	console.info(greeting + ", " + this.name);
}
const person = { name: "Fa-ce" };
greet.call(person, "Hello"); // Hello, Fa-ce
greet.apply(person, ["Test"]); // Test, Fa-ce

const boundGreet = greet.bind(person);
boundGreet("Hi"); // Hi, Fa-ce

面向对象的介绍

  • 什么是对象
  • 什么是面向对象
    • 面向过程
    • 对象对象(OOP)
  • 面向对象编程的三大特性
    • 封装
    • 继承
    • 多态

e.g.: 处理学生成绩表,通过面向过程的方式,需要定义很多函数,如:添加学生、删除学生、修改学生、查询学生等。而通过面向对象的方式,只需要定义一个学生类,然后通过这个类创建学生对象,就可以直接调用对象的方法来处理学生成绩表。

js 复制代码
var std1 = { name: "John", age: 20 };
var std2 = { name: "Jane", age: 22 };

处理学生程力可以通过函数去实现,例如:打印

js 复制代码
function printScore(student) {
	console.log(`${student.name} scored ${student.score}`);
}

假如使用面向对象:

js 复制代码
function printScore(name, score) {
	this.name = name;
	this.score = score;
	this.printScore = function () {
		console.log(`${this.name} scored ${this.score}`);
	};
}

// 根据模板创建具体实例对象
var std1 = new printScore("John", 90);
var std2 = new printScore("Jane", 80);

/* ****** class ******* */
class Student {
	constructor(name, age) {
		this.name = name;
		this.age = age;
	}
	printScore() {
		console.log(`${this.name} scored ${this.score}`);
	}
}
var std3 = new Student("John", 90);
var std4 = new Student("Jane", 80);

/* 打印成绩 */
std1.printScore();
std2.printScore();
std3.printScore();
std4.printScore();

基于函数的面向对象实现

  1. 创建对象
  • new Object()
js 复制代码
const person = new Object();
person.name = "Fa-ce";
person.age = 18;
  • 字面量
js 复制代码
const person = {
	name: "Fa-ce",
	age: 18,
	sayName: function () {},
};
  1. 工厂函数 => 构造函数
  • 引入工厂函数
js 复制代码
function createPerson(name, age) {
	return {
		name: name,
		age: age,
		sayName: function () {
			console.log(this.name);
		},
	};
}

const person_0 = createPerson("Fa-ce", 18);
  • 构造函数的问题:构造函数中的方法每次实例化都会重复创建,浪费内存;不利于代码维护与优化
js 复制代码
function Person(name, age) {
	this.name = name;
	this.age = age;
	this.sayName = function () {
		console.log(this.name);
	};
}

const person_1 = new Person("Fa-ce", 18);
const person_2 = new Person("Fa-ce1", 19);

// 每次调用 new Person(...) 时,this.sayName = function () {...} 都会生成一个新的函数实例。
// person_1.sayName !== person_2.sayName,这两个是不同的函数对象,即使它们内容完全一样。
  1. new 做了哪些事情
    • 创建一个空对象
    • 将构造函数的作用域付给新对象(this 指向新对象)
    • 执行构造函数中的代码(为新对象添加属性)
    • 返回新对象
js 复制代码
function Person(name, age) {
	// 使用 new 调用 Person() 时, 会创建一个对象
	// var instance = {}
	// 让内部的 this 指向 instance 对象
	// this = instance
	// 接下来所有针对 this 的操作, 都会针对 instance 对象
	return this;
}

console.info(p1.constructor === Person); // true
console.info(p2.constructor === Person); // true
console.info(p1.constructor === p2.constructor); // true

console.info(p1 instanceof Person); // true
  • 构造函数的问题:通过构造函数创建的实例,每个实例都有自己的一份方法
js 复制代码
function Person(name, age) {
	this.name = name;
	this.age = age;
	this.sayName = function () {
		console.log(this.name);
	};
}

const person_1 = new Person("Fa-ce", 18);
const person_2 = new Person("Fa-ce1", 19);

// 每次调用 new Person(...) 时,this.sayName = function () {...} 都会生成一个新的函数实例。
console.info(person_1.sayName === person_2.sayName); // false

/* ******* 将 sayName 函数写在外部  ******* */
function sayName() {
	console.log(this.name);
}

function Person(name, age) {
	this.name = name;
	this.age = age;
	this.sayName = sayName;
}

const person_1 = new Person("Fa-ce", 18);
const person_2 = new Person("Fa-ce1", 19);
// 每次构造不会生成新的函数实例,而是指向同一个函数
console.info(person_1.sayName === person_2.sayName); // true
  • 原型 和 原型链
js 复制代码
function Person(name, age) {
	this.name = name;
	this.age = age;
}
Person.prototype.type = "human";
Person.prototype.sayName = function () {
	console.info(this.name);
};

const person_1 = new Person("Fa-ce", 18);
const person_2 = new Person("Fa-ce1", 19);

console.info(person_1.type); // human
console.info(person_2.type); // human
console.info(person_1.sayName === person_2.sayName); // true

/* ****    原型链    **** */
function F() {
	const sayHi = function () {};
}
console.info(F.prototype); // {constructor: ƒ}
console.info(F.prototype.constructor === F); // true

var instance = new F();
console.info(instance.__proto__ === F.prototype); // true

es6 面向对象

  • Class(类) 和 Object(对象)
    • 类是一种特定对象中方法和变量的模板定义
    • 对象是类的具体示例,并且在内存中分配
js 复制代码
// 定义类
class Form {
	submit() {
		console.info(this.name + "" + this.roll + "submitted");
	}
	cancel() {
		console.info(this.name + "" + this.roll + "cancelled");
	}
	fill(give_name, give_roll) {
		this.name = give_name;
		this.roll = give_roll;
	}
}

// 创建对象
var student = new Form();
student.fill("Fa-ce", 123);
student.submit();
student.cancel();
  • Constructor (构造函数)
js 复制代码
class Form {
	constructor() {
		// 构造函数,初始化默认的 name 、roll
		this.name = "Fa-ce";
		this.roll = "admin";
	}
	submit() {
		console.info(this.name + "" + this.roll + "submitted");
	}
	cancel() {
		console.info(this.name + "" + this.roll + "cancelled");
	}
	fill(give_name, give_roll) {
		this.name = give_name;
		this.roll = give_roll;
	}
}

// 创建对象
const student1 = new Form();
const student2 = new Form();
student1.fill("Fa-ce", 123);
student1.submit();
student2.fill("Fa-ce1", 124);
student2.cancel();
  • 无参数构造函数:构造函数没有参数,不需要在构造函数中添加参数
js 复制代码
class Example {
	constructor() {
		this.name = "test";
	}
}
  • 有参数构造函数:构造函数有参数,需要在构造函数中添加参数
js 复制代码
class Example {
	constructor(name) {
		this.name = name;
	}
}

分割线 ,未写完......

  • 继承
js 复制代码
class Student extends Form {
	constructor() {
		super();
		this.name = "test";
	}
}
  • Inheritance 继承
js 复制代码
class Animal {
	constructor(name, age, color) {
		this.name = name;
		this.age = age;
		this.color = color;
	}
	run() {
		console.info(this.name + " is running");
	}
	shout() {
		console.info(this.name + " is shouting");
	}
	sleep() {
		console.info(this.name + " is sleeping");
	}
}
class Dog extends Animal {
	constructor(name, age, color, breed) {
		super(name, age, color);
		this.breed = breed;
	}
	run() {
		console.info(this.name + " is running");
	}
	shout() {
		console.info(this.name + " is shouting");
	}
	sleep() {
		console.info(this.name + " is sleeping");
	}
}

const dog = new Dog("Fa-ce", 18, "red", "Bulldog");
dog.run();
dog.shout();
dog.sleep();
  • 多态
js 复制代码
class Animal {
  
}
  • 访问修饰符

    • Public:可以从其他任何类中访问

    • Protected:受保护的成员,可以在同一类及其子类中访问

    • Private:私有成员,只能在同一个类中访问

  • 静态方法

    • static:给类定义一个静态方法或字段,静态方法是属于类本身的方法,而不是类的具体实例方法
    • 静态方法:静态方法属于类本身,而不是类的实例。静态方法不能通过类的实例调用,只能通过类本身调用。静态方法可以访问类的静态属性和方法,但不能访问类的实例属性和方法。
    • 静态方法:静态方法可以用于实现一些与类本身相关的功能,而不需要创建类的实例。例如,可以定义一个静态方法来计算类的实例数量,或者定义一个静态方法来生成类的实例。
  • Getter 和 Setter

    • getter 不应该加 (),应该直接访问属性,例如:console.log(person_0.getName);
    • setter 不能当作函数调用,而应该直接赋值,例如:person_0.setName = "newName";
    • 如果想要用 () 方式调用,就应该 不用 getset 关键字,直接创建普通方法
  • instanceOf

    • 检查一个对象是否是某个类或者接口的实例
  • 封装

    • 一种限制,对对象某些组件或属性直接访问的方式
  • 多态

  • 抽象

复制代码
复制代码
复制代码
复制代码
相关推荐
Boilermaker19921 小时前
【Java EE】SpringIoC
前端·数据库·spring
中微子1 小时前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上10241 小时前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y2 小时前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁2 小时前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry2 小时前
Fetch 笔记
前端·javascript
拾光拾趣录2 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟2 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan2 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson2 小时前
青苔漫染待客迟
前端·设计模式·架构