编程范式
1:命令式编程
命令机器去做事情,这样不管你想要的是什么,他都会按照你的命令实现。
1:面向过程
分析解决问题所需要的步骤,然后一步步实现。
2:面向对象
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述解决问题中华步骤的行为。
**注:**面向对象并不是完全脱离面向过程的,也就是说,就算好似采用面向对象的思想,里面也会有面向过程的步骤,只不过通过面向对象可以给我们节省了很多步骤,因为这些步骤通过对象本身实现了。
特征
#####1:封装
内部运作隐藏在对象里,只有基本功能暴露给最终用户。
#####2:继承
新对象继承一个现有对象的特性,然会添加一些新的特效。
#####2:多态
不同的对象可以共享相同的方法。还能够用一些特定的方法覆盖原有的方法。
类
类是对象的一种概括,而对象是类的一种具体实现。
例:
class Person{
public $name;
public $gender;
public $age;
function __construct($name, $gender, $age){
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
2:声明式编程
告诉机器你想要的是什么,让机器想出如何去做。
1:领域专用语言
DSL:主要指一些对应专门领域的高层编程语言,和通用编程语言的概念相对。
2:函数编程
是一种编程模型,将计算机运算看作是数学中函数的计算。在函数式编程中,变量只是一个名称,而不是存储单元。
####原型对象
在js中,每一个对象,都有一个原型对象。而原型对象上面也有一个自己的原型对象,一层一层向上找,最终会到达null。
####对象分类
1:原生对象
内置对象
js中本身所内置的。
自定义对象
开发人员自定义的对象
2:宿主对象
基于对象创建新对象
const person = {
arms: 2,
legs: 2,
walk() { console.log('walking'); }
}
const xiejie = Object.create(person); console.log(xiejie.arms); // 2
console.log(xiejie.legs); // 2 xiejie.walk(); // walking
console.log(xiejie.__proto__ === person); // true
原型相关方法
1: prototype 和_proto_ c
prototype是构造函数上面的一个属性,指向一个对象,这个对象是该构造函数实例化出来的对象的原型对象。实例化出来的对象可以通过_proto_来找到自己的原想对象。
const arr = [1,2,3,4,5]; console.log(Array.prototype); console.log(arr.__proto__);
console.log(Array.prototype === arr.__proto__);
2: Object.getPrototypeOf()方法
查找原型对象
let arr = [1,2,3,4,5] console.log(Object.getPrototypeOf(arr)); // []
console.log(arr.__proto__); // []
console.log(Object.getPrototypeOf(arr) === arr.__proto__); // true
#####3:constructor属性
查对象构造函数
const arr = [1,2,3,4,5]; console.log(arr.constructor); // [Function: Array]
4.instanceof操作符
判断一个对象是否是一个构造函数的实例。返回true或false。
const arr = [1,2,3,4,5]; console.log(arr instanceof Array); // true
console.log(arr instanceof Number); // false
-
isPrototypeOf() 方法
返回一个布尔值,检测一个对象是否是一个实例对象的原型对象。 -
hasOwnProperty()
判断一个属性是定义在对想本身上面还是从原型对象上面继承而来。返回布尔值。
构造函数
1.构造函数创建对象
使用函数来模拟其他面向对象语言中的类。
用于实列化对象的函数,我们将其称之为构造函数。
咧:
const Computer = function(name,price){
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function(){
console.log(`这是一台{this.name}电脑`);
}
当使用new运算符调用函数时,该函数总会返回一个对象,通常情况下,构造函数里面的this就指向返回这个对象。
咧:
const Computer = function(name,price){
this.name = name; this.price = price;
}
Computer.prototype.showSth = function(){
console.log(this); // 打印出this所指向的对象
console.log(`这是一台{this.name}电脑`);
}
const apple = new Computer("苹果",12000);
console.log(apple.name);// 苹果
console.log(apple.price);// 12000
apple.showSth();// Computer { name: '苹果 ', price: 12000 } 这是一台苹果电脑
const asus = new Computer("华硕",5000);
console.log(asus.name);// 华硕
console.log(asus.price);// 5000
asus.showSth();// Computer { name: ' 华硕', price: 5000 } 这是一台华硕电脑
2.构造函数显式返回内容
构造函数显式返回object类型对象的区别
咧:
const Computer = function (name, price) {
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function () {
console.log(this); // 打印出this所指向的对象
}
const apple = new Computer("苹果", 12000);
console.log(apple.name); // 苹果
apple.showSth(); // Computer { name: ' 苹果 ', price: 12000 }
3.ECMAScript 6中类的声明
使用class关键字来声明一个类来,然后从类里面实列化对象
咧:
class Computer {
// 构造器
constructor(name, price) {
this.name = name;
this.price = price; }
//原型方法
showSth() {
console.log(`这是一台${this.name}电脑`);
}
} const apple = new Computer("苹果", 12000);
console.log(apple.name); // 苹果
console.log(apple.price); // 12000
apple.showSth(); // 这是一台苹果电脑
4.静态方法
又被称为类方法,就是通过类来调用的方法。静态方法的好处在于不需要实例化对象,直接通过类就能够进行方法的调用。
咧:
class Computer {
// 构造器
constructor(name, price) {
this.name = name;
this.price = price; }
//原型方法
showSth() {
console.log(`这是一台${this.name}电脑`);
}
// 静态方法
static comStruct() {
console.log("电脑由显示器,主机,键鼠组成");
}
}
Computer.comStruct(); //电脑由显示器,主机,键鼠组成
如果书写的式构造函数,也有办法来模拟静态方法,直接将方法挂在构造函数上。
咧:
const Computer = function (name, price) {
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function () {
console.log(`这是一台${this.name}电脑`);
}
//静态方法直接通过 Computer这个构造函数来调用
Computer.comStruct = function () {
console.log("??????????????");
}
Computer.comStruct(); // ??????????????
面对对象3大特征
1.封装
指隐藏内部的细节,不暴露在外面。目的就是将信息隐藏。
const Computer = function(name,price){
this.name = name;
this.price = price;
this.sayPrice = function () {
console.log(`价格${_price}`);
}
}
Computer.prototype.showSth = function () {
console.log(`这是一台${this.name}电脑`);
}
const apple = new Computer("苹果", 12000);
apple.sayPrice(); // 价格12000
2.继承
1.继承基本介绍
面向对象里面的继承是指一个子类去继承一个父类。子类继承父类之后,父类所有的属性和方法都自动拥有了
好处:代码复用。
缺点:1)会出现“大猩猩与香蕉”问题
2)也会遇到“菱形继承”(只会在多继承里面才会出现)
2.对象冒充
对象冒充,就是用父类(构造函数)去充当子类的属性
咧:
const Person = function (name, age) {
this.name = name;
this.age = age;
}
const Student = function (name, age, gender, score) {
this.temp = Person; // 将Person构造函数Student的一个属性
this.temp(name, age); // 给Person构造函数里面的this.name以及this.age赋值
delete this.temp; // this.temp 已经无用,将其删除
this.gender = gender;
this.score = score;
}
const xiejie = new Student("哈哈", 18, "男", 100); console.log(xiejie.name); // 哈哈
console.log(xiejie.age); // 18
console.log(xiejie.gender); //男
console.log(xiejie.score); // 100
使用对象冒充来实现继承也有一个缺陷,那就是无法继承到原型对象上面的属性。
咧:
const Person = function (name, age) {
this.name = name;
this.age = age;
}
Person.prototype.test = "this is a test";
const Student = function (name, age, gender, score) {
this.temp = Person; // 将Person构造函数Student的一个属性
this.temp(name, age); // 给Person构造函数里面的this.name以及this.age赋值
delete this.temp; // this.temp 已经无用,将其删除
this.gender = gender;
this.score = score;
}
const xiejie = new Student("哈哈", 18, "男", 100); console.log(xiejie.name); // 哈哈
console.log(xiejie.age); // 18
console.log(xiejie.gender); //男
console.log(xiejie.score); // 100
console.log(xiejie.test); // undefined
3.方法借用模式
call()和apply()方法
Function.apply(obj?args)方法能接收两个函数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args->arguments)
Function.call(obj?[param1[?param2[?..[?paramN]]]])
obj:这个对象将代替Function类里this对象
params:这个是一个参数列表
call()实现继承示列:
const Person = function (name, age) {
this.name = name;
this.age = age;
}
Person.prototype.test = "this is a test";
const Student = function (name, age, gender, score) {
// 将Person构造函数应用到this 里面
// this 后面是参数
Person.call(this, name, age);
this.gender = gender;
this.score = score;
}
const xiejie = new Student("哈哈", 18, "男", 100); console.log(xiejie.name); // 哈哈
console.log(xiejie.age); // 18
console.log(xiejie.gender); // 男
console.log(xiejie.score); // 100
console.log(xiejie.test); // undefined
apply()实现继承示列:
const Person = function (name, age) {
this.name = name;
this.age = age;
}
Person.prototype.test = "this is a test";
const Student = function (name, age, gender, score) {
// 将Person构造函数应用到this 里面
// this 后面是参数
## Person.apply(this,[name,age]);
this.gender = gender;
this.score = score;
}
const xiejie = new Student("哈哈", 18, "男", 100); console.log(xiejie.name); // 哈哈
console.log(xiejie.age); // 18
console.log(xiejie.gender); // 男
console.log(xiejie.score); // 100
console.log(xiejie.test); // undefined
4.原型继承
这种方式的核心思路就是改变构造函数的prototype的指向,使其指定到我们想要继承的类的实列对象上面
咧:
const Person = function (name, age) {
this.name = name;
this.age = age;
}
Person.prototype.test = "this is a test";
const Student = function (name, age, gender, score) {
// 将Person构造函数应用到this里面
// this后面是参数
Person.apply(this, [name, age]);
this.gender = gender;
this.score = score;
}
Student.prototype = new Person(); // 改变Student构造函数的原型对象
const xiejie = new Student("哈哈", 18, "男", 100); console.log(xiejie.name); //哈哈
console.log(xiejie.age); // 18
console.log(xiejie.gender); // 男
console.log(xiejie.score); // 100
console.log(xiejie.test); // this is a test
5.ECMAScript 6 继承方式
可以使用extends关键字来实现继承
咧:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(`my name is ${this.name}`);
}
}
class Student extends Person {
constructor(name, age, gender, score) {
super(name, age); // super代表访问父类的构造函数
this.gender = gender;
this.score = score;
}
learn() {
console.log("I\'m learning");
}
}
const xiejie = new Student("xiejie", 18, "male", 100); console.log(xiejie.name); // xiejie
console.log(xiejie.age); // 18
console.log(xiejie.gender); // male
console.log(xiejie.score); // 100
xiejie.sayName(); // my name is xiejie
xiejie.learn(); // I'm learning
3多态
1.多态简介
含义:同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果。
换句话说,给不同的对象发送同一个消息的时候,这些对象会根据这个消息分别给出不同的反馈。
2.实现多态
const duck = {
name: "鸭子",
makeSound: function () {
console.log("嘎嘎嘎");
}
};
const chicken = {
name: "鸡",
makeSound: function () {
console.log("咯咯咯");
}
};
const animalSound = function (obj) {
obj.makeSound();
}
animalSound(duck); // 嘎嘎嘎
animalSound(chicken); // 咯咯咯
在 ECMAScript 6 中我们也可以在子类里面书写和父类相同的方法名来进行覆盖
咧:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(`my name is ${this.name}`);
}
}
class Student extends Person {
constructor(name, age, gender, score) {
super(name, age); // super代表访问父类的构造函数
this.gender = gender;
this.score = score;
}
sayName() {
console.log(`haha,I'm ${this.name}`);
}
learn() {
console.log("I\'m learning");
}
}
const xiejie = new Student("哈哈", 18, "男", 100);
xiejie.sayName(); // haha,I'm 哈哈
const song = new Person("宋", 20);
song.sayName(); // my name is 宋
3.多态的意义
多态的最根本的好处在于,你不必再向对象询问”你是什么类型“后根据得到的答案调用对象的某个行为,你只需要调用该行为就是了,其他的一切多态机制会为你安排妥当。
this的指向
1.this指向的默认情况
1.this指向当前对象
如果是在对象里面使用this,则指向当前对象。this可以用在方法内,获取对对象属性的访问。。
咧:
const person = {
name: 'xiejie',
age: 18,
intro: function () {
console.log(this); // { name: 'xiejie', age: 18, intro: [Function: i ntro] }
console.log(`My name is ${this.name},I'm ${this.age} years old`); // My name is xiejie,I'm 18 years old
}
}
person.intro();
2.普通函数中的this指向
如果是普通调用函数,this则指向全局对象
咧:
const test = function () {
console.log(this); // global 对象
// 在 node里面 , 全局对象就是global 对象
// 如果是在浏览器里面,那么全局对象代表window对象
}
test();