JavaScript设计模式(一):面向对象编程 - 继承

news/2024/5/14 17:09:41/文章来源:https://blog.csdn.net/weixin_43526371/article/details/127241878

JavaScript设计模式 - 面向对象编程

  • 灵活的语言-JavaScript
    • 用对象收编变量
    • 对象的另一种形式(函数对象)
    • 真假对象(闭包和类)
    • 一个检测类
    • 函数的祖先
  • 写的都是看到的-面向对象编程
    • 创建一个类(三种方式)
    • 类的属性和方法
    • 通过闭包来实现类的静态变量定义,使之更像一个整体
    • 忘记 `new` 怎么办?
    • 子类的原型对象-类式继承
    • 创建即继承-构造函数继承
    • 将优点为我所用-组合继承
    • 洁净的继承者-原型式继承
    • 如虎添翼-寄生式继承(对原型式继承的增强)
    • 终极继承者-寄生组合式继承(`寄生式继承`和`构造函数继承`的组合)
    • 老师不止一位-多继承
    • 多种调用方式-多态

灵活的语言-JavaScript

实现一个验证表单的功能,需要验证用户名、邮箱、密码

用对象收编变量

let CheckObject = {checkName: function () {// 验证姓名},checkEmail: function () {// 验证邮箱},checkPassword: function () {// 验证密码},
}

对象的另一种形式(函数对象)

  • 缺点:
    • 对象类不能复制一份(或者说这个对象类在用new关键字创建新的对象时,新创建的对象是不能继承这些方法的)
let CheckObject = function () {
};
CheckObject.checkName = function () {// 验证姓名
}
CheckObject.checkEmail = function () {// 验证邮箱
}
CheckObject.checkPassword = function () {// 验证密码
}

真假对象(闭包和类)

实现复制功能,人手一份

// 闭包 - 内部函数返回到外部
let CheckObject = function () {return {checkName: function () {// 验证姓名},checkEmail: function () {// 验证邮箱},checkPassword: function () {// 验证密码},}
}
let a = CheckObject();
a.checkName();
// 类 - 对象的实例化
let CheckObject = function () {this.checkName = function () {// 验证姓名}this.checkEmail = function () {// 验证邮箱}this.checkPassword = function () {// 验证密码}
}
let a = new CheckObject();
a.checkName();

一个检测类

  • 以上方法通过new关键字创建对象时,新创建额对象都会对类的this上的属性进行复制,所以这些新创建的对象都会有自己的一套方法,但缺点是消耗大,因为每次都需要复制一套方法

将方法创建在类的原型上,这样调用的方法就都会是同一个,减小消耗

let CheckObject = function () {
};
CheckObject.prototype.checkName = function () {// 验证姓名return this;
}
CheckObject.prototype.checkEmail = function () {// 验证邮箱return this;
}
CheckObject.prototype.checkPassword = function () {// 验证密码return this;
}
let a = new CheckObject();
a.checkName().checkEmail().checkPassword();

函数的祖先

抽象出一个可以添加方法功能的方法

Function.prototype.addMethod = function (name, fn) {this[name] = fn;
}let methods = function () {
}; // 或者 let methods = new Function();methods.addMethod('checkName', function () {// 验证姓名
});
methods.addMethod('checkEmail', function () {// 验证邮箱
});
methods.addMethod('checkPassword', function () {// 验证密码
});

链式添加方法功能并链式调用(以下两个方法只能为自身添加方法)

在这里插入图片描述

// 链式添加-方式一 (链式调用)
Function.prototype.addMethod = function (name, fn) {this[name] = fn;
}let methods = function () {
}; // 或者 let methods = new Function();methods.addMethod('checkName', function () {// 验证姓名console.log('验证姓名');return this;
});
methods.addMethod('checkEmail', function () {// 验证邮箱console.log('验证邮箱');return this;
});
methods.addMethod('checkPassword', function () {// 验证密码console.log('验证密码');return this;
});
methods.checkName().checkEmail().checkPassword(); // 验证姓名 验证邮箱 验证密码
// 链式添加-方式二 (方式一的改进版本) 存在消耗问题
Function.prototype.addMethod = function (name, fn) {this[name] = fn;return this;
}let methods = function () {
}; // 或者 let methods = new Function();methods.addMethod('checkName', function () {// 验证姓名console.log('验证姓名');return this;
}).addMethod('checkEmail', function () {// 验证邮箱console.log('验证邮箱');return this;
}).addMethod('checkPassword', function () {// 验证密码console.log('验证密码');return this;
});
methods.checkName().checkEmail().checkPassword(); // 验证姓名 验证邮箱 验证密码

改进:在原型上添加方法功能的方法

在这里插入图片描述

// 链式添加-方式三 (方式二的改进版本) 减小消耗
Function.prototype.addMethod = function (name, fn) {this.prototype[name] = fn;return this;
}let Methods = function () {
}; // 或者 let methods = new Function();Methods.addMethod('checkName', function () {
// 验证姓名console.log('验证姓名');return this;
}).addMethod('checkEmail', function () {
// 验证邮箱console.log('验证邮箱');return this;
}).addMethod('checkPassword', function () {
// 验证密码console.log('验证密码');return this;
});let m = new Methods();
m.checkName().checkEmail().checkPassword(); // 验证姓名 验证邮箱 验证密码

写的都是看到的-面向对象编程

创建一个类(三种方式)

方式一:函数this创建方式

在这里插入图片描述

// 1.函数this创建方式
function Book(id, bookName, price) {this.id = id;this.bookName = bookName;this.price = price;
}let book = new Book('abc', 'JS设计模式', 123.12);
console.log(book);

方式二:class-this创建方式

在这里插入图片描述

// 2.class-this创建方式
class Book {constructor(id, bookName, price) {this.id = id;this.bookName = bookName;this.price = price;}
}let book = new Book('abc', 'JS设计模式', 123.12);
console.log(book);

方式三:原型创建方式 (setBookInfo方法在原型上)

在这里插入图片描述

// 3.原型创建方式 setBookInfo方法在原型上
let Book = function () {
};
Book.prototype.setBookInfo = function (id, bookName, price) {this.id = id;this.bookName = bookName;this.price = price;
}
let book = new Book();
book.setBookInfo('abc', 'JS设计模式', 123.12);
console.log(book);

图解

在这里插入图片描述

类的属性和方法

  • 属性和方法
    • 私有属性
    • 私有方法
    • 特权方法
    • 对象公有属性
    • 对象公有方法
    • 构造器
    • 类静态公有属性
    • 类静态公有方法

在这里插入图片描述

let Person = function (id, name, age) {// 私有属性let topSecret = '私密';// 私有方法function secretFn() {}// 特权方法// 		能访问到自身的一些属性和方法,所以被称为特权方法;// 		在对象创建时可以实例化对象的一些属性,又可被用作构造器;this.setName = function (n) {this.name = n;};this.setAge = function (a) {this.age = a;};// 对象公有属性this.id = id;// 对象公有方法(让他说出自己的秘密)this.publicFn = function () {console.log(topSecret);};// 构造器this.setName(name);this.setAge(age);
}// 类静态公有属性(new过的对象不能访问)
Person.num = 10;
// 类静态公有方法(new过的对象不能访问)
Person.say = function () {
};Person.prototype = {// 公有属性publicProp: '原型上的属性!',// 公有方法publicMethod: function () {}
}let lee = new Person('abc', 'ProsperLee', 18);console.log('Person', {Person});
console.log('lee', lee);lee.publicFn(); // 私密lee.publicProp; // 原型上的属性!Person.num; // 10lee.say; // undefined

在类的外部通过.语法定义的属性和方法和在类的外部通过prototype定义的属性和方法的区别:

function Person() {// this.say1(); // Error TypeError: this.say1 is not a functionthis.say2(); // Hello Lee!!!
}Person.say1 = function () {console.log('Hello World!!!');
};Person.prototype = {say2() {console.log('Hello Lee!!!');}
};let person = new Person();// person.say1(); // Error TypeError: person.say1 is not a function
person.say2(); // Hello Lee!!!
  • 区别:
    • 在类的外部通过.语法定义的属性和方法:
      • 不可通过 this 或者 new 的实例对象进行访问;
      • 可通过类进行调用 Person.say1();;
    • 在类的外部通过prototype定义的属性和方法:
      • 可通过 this 或者 new 的实例对象进行访问;
      • 不可通过类进行调用 Person.say2(); // Error;
      • 可通过 Person.prototype.方法 进行调用;

通过闭包来实现类的静态变量定义,使之更像一个整体

在这里插入图片描述

// 利用闭包实现
let Book = (function () {// 静态私有变量let bookNum = 0;// 静态私有方法let checkBook = function (name) {};// 创建类function _book(newId, newName, newPrice) {// 私有变量let name, price;// 私有方法function checkID(id) {}// 特权方法this.getName = () => name;this.getPrice = () => price;this.setName = function (n) {name = n;};this.setPrice = function (p) {price = p;};// 公有属性this.id = newId;name = newName;price = newPrice;// 公有方法this.copy = function () {};bookNum++;if (bookNum > 100) {throw new Error('我们仅出版100本书!!!');}// 构造器this.setName(name);this.setPrice(price);}// 构造原型_book.prototype = {// 静态公有属性isJSBook: true,// 静态公有方法display() {},};// 返回类return _book;})();let book = new Book('abc', 'JS设计模式', '12.34');console.log('Book', {Book});console.log('book', book);
book.getName(); // 'JS设计模式'
book.getPrice(); // '12.34'

忘记 new 怎么办?

let Book = function (id, bookName, price) {this.id = id;this.bookName = bookName;this.price = price;
}
let book = Book('abc', '《JS设计模式》', 12.34);
console.log(book);               // undefined
console.log(window.id);          // abc              this指向了window
console.log(window.bookName);    // 《JS设计模式》     this指向了window
console.log(window.price);       // 12.34            this指向了window

解决办法:

let Book = function (id, bookName, price) {// 判断this是否是当前这个对象(如果是说明是用new创建的)if (this instanceof Book) {this.id = id;this.bookName = bookName;this.price = price;} else { // 否则重新创建这个对象return new Book(id, bookName, price);}
}
let book = Book('abc', '《JS设计模式》', 12.34);
console.log(book);                  // Book {id: 'abc', bookName: '《JS设计模式》', price: 12.34}
console.log(window.id);             // undefined
console.log(window.bookName);       // undefined
console.log(window.price);          // undefined

子类的原型对象-类式继承

在这里插入图片描述

在这里插入图片描述

// 父类
function SuperClass() {this.superValue = true;
}// 为父类添加共有方法
SuperClass.prototype.getSuperValue = function () {return this.superValue;
};// 子类
function SubClass() {this.subValue = false;
}// 继承父类
SubClass.prototype = new SuperClass();
// 为子类添加共有方法
SubClass.prototype.getSubValue = function () {return this.subValue;
};let superClass = new SuperClass();
let subClass = new SubClass();console.log(superClass, subClass);
  • instanceof 通过判断对象的 prototype链 来确定这个对象是否是某个类的实例,并不是表示两者的继承关系
  • 所有对象都是 Object 的实例
console.log(superClass instanceof SuperClass);          // true
console.log(subClass instanceof SubClass);              // trueconsole.log(subClass instanceof SuperClass);            // true
console.log(SubClass instanceof SuperClass);            // falseconsole.log(SubClass.prototype instanceof SuperClass);  // true		契合以上判断条件
console.log(SubClass instanceof Object);  				// true		契合以上判断条件

类式继承的缺点:

// 父类
function Father() {this.str = 'Lee';this.data = ['Lee'];
}// 子类
function Son() {
}// 继承父类
Son.prototype = new Father();let instance1 = new Son();
let instance2 = new Son();console.log(instance1.data, instance2.data);  // ['Lee'] ['Lee']instance1.str = 'Tom';
instance1.data.push(18);console.log(instance1.str, instance2.str);    // Tom Lee
console.log(instance1.data, instance2.data);  // (2)['Lee', 18] (2)['Lee', 18]
  1. 当一个子类的实例``更改子类原型从父类构造函数继承来的共有属性就会直接影响到其他子类
    • 比如: 修改 instance1 原型上继承来自父类的引用类型的值时, instance2 获取到的值也被改变了
  2. 无法在实例化子类的同时向父类传递参数
    • 比如: new Son(参数); 的时候没发把参数传递给父类,因为子类实现的继承是靠其原型等于父类的实例化实现的

创建即继承-构造函数继承

利用 call 改变函数作用环境

在这里插入图片描述

// 父类
function Father(id) {// 值类型公有属性this.id = id;// 引用类型公有属性this.data = ['Lee', 'Tom'];
}// 父类原型方法
Father.prototype.showData = function () {console.log(this.data);
}// 子类
function Son(id) {// 继承父类Father.call(this, id);
}let instance1 = new Son('id-001');
let instance2 = new Son('id-002');instance1.data.push('张三');instance1.id;       // 'id-001'
instance1.data;     // ['Lee', 'Tom', '张三']instance2.id;       // 'id-002'
instance2.data;     // ['Lee', 'Tom']instance1.showData(); // Error TypeError: instance1.showData is not a function
instance2.showData(); // Error TypeError: instance2.showData is not a function

构造函数继承缺点:

  • 无法调用父类原型上的属性和方法(无法继承来自原型上的属性和方法)
    • 比如: instance1.showData();instance2.showData(); 会报错

将优点为我所用-组合继承

在这里插入图片描述

// 父类
function Father(fatherName) {// 值类型公有属性this.fatherName = fatherName;// 引用类型公有属性this.friends = ['Lee', 'Tom'];
}Father.prototype.getFatherName = function () {console.log(this.fatherName);
};// 子类
function Son(fatherName, myName) {// 构造函数式继承类Father.call(this, fatherName);// 子类中的公有属性this.myName = myName;
}// 类式继承 - 子类继承父类
Son.prototype = new Father();Son.prototype.getMyName = function () {console.log(this.myName);
};console.log({Father}, {Son});let son = new Son('汤姆', 'Tom');console.log(son);

组合 类式和构造函数式 继承的缺点:

  • 父类的构造函数执行了两遍
    • 使用构造函数式继承时执行了一次父类的构造函数
    • 实现子类原型的类式继承时又调用了一遍父类的构造函数

洁净的继承者-原型式继承

在这里插入图片描述

// 原型式继承
function inheritObject(o) {// 声明一个 过渡函数对象function F() { }// 过渡对象 的 原型 继承 父对象F.prototype = o;// 返回过度对象的一个实例,该实例的原型继承了父对象return new F();
}let friends = ['Lee', 'Tom'];let obj1 = inheritObject({ getName() { console.log('obj1', this.name); } });
obj1.name = 'Lee';
obj1.friends = friends;let obj2 = inheritObject({ getName() { console.log('obj2', this.name); } });
obj2.name = 'Tom';
obj2.friends = friends;

原型式继承的缺点:

在这里插入图片描述

obj1.friends.push('张三'); // friends.push('张三');
console.log('【obj1】', obj1, '【obj2】', obj2);
  • 当一个子类的实例``更改子类从父类构造函数继承来的共有属性就会直接影响到其他子类的实例
    • 比如: 修改 obj1 上继承来自父类的引用类型的值时, obj2 获取到的值也被改变了

如虎添翼-寄生式继承(对原型式继承的增强)

其实寄生式继承就是对原型继承的第二次封装,并且在这第二次封装过程中对继承的对象进行了拓展,这样新创建的对象不仅仅有父类中的属性和方法而且还添加新的属性和方法

在这里插入图片描述

// 基类
let userInfo = { name: 'Lee', age: 18 };
let friends = ['Lee', 'Tom'];// 原型式继承
function inheritObject(o) {// 声明一个 过渡函数对象function F() { }// 过渡对象 的 原型 继承 父对象F.prototype = o;// 返回过度对象的一个实例,该实例的原型继承了父对象return new F();
}function createObj(obj) {// 原型式继承let o = inheritObject(obj);// 拓展新对象o.friends = friends;o.getName = function () {console.log(this.name);}// 返回拓展后的新对象return o;
}let obj1 = createObj(userInfo);
let obj2 = createObj(userInfo);obj1.friends.push('张三');console.log('【obj1】', obj1, '【obj2】', obj2);

寄生式继承缺点:

  • 与原型式继承相同

终极继承者-寄生组合式继承(寄生式继承构造函数继承的组合)

解决了子类实例化 修改公有属性 影响其他实例化的对象 的问题

在这里插入图片描述

// 原型式继承
function inheritObject(o) {// 声明一个 过渡函数对象function F() { }// 过渡对象 的 原型 继承 父对象F.prototype = o;// 返回过度对象的一个实例,该实例的原型继承了父对象return new F();
}/*** 寄生组合式继承 - 寄生式继承,继承原型* @param {class} sonClass 子类* @param {class} fatherClass 父类*/
function inheritPrototype(sonClass, fatherClass) {// 赋值一份父类的原型副本保存在变量中let p = inheritObject(fatherClass.prototype);// 修正因为重写子类原型导致子类的constructor属性被修改p.constructor = sonClass;// 设置子类的原型sonClass.prototype = p;
}// 父类
function Father(fatherName) {this.fatherName = fatherName;this.friends = ['Lee', 'Tom'];
}Father.prototype.getFatherName = function () {console.log(this.fatherName);
}// 子类
function Son(fatherName, sonName) {Father.call(this, fatherName);this.sonName = sonName;
}// 寄生式继承父类原型
inheritPrototype(Son, Father);Son.prototype.getSonName = function () {console.log(this.sonName);
}let son1 = new Son('汤姆', 'Tom');
let son2 = new Son('张三', 'ZhangSan');son1.getFatherName();   // 汤姆
son1.getSonName();      // Tomson1.friends.push('张三');console.log('【son1】', son1, '【son2】', son2);

原理图

在这里插入图片描述

老师不止一位-多继承

单继承

在这里插入图片描述

// 单继承 属性复制继承(此示例使用的是浅克隆)
var extend = function (target, source) {// 遍历源对象中的属性for (var property in source) {// 将源对象中的属性复制到目标对象中target[property] = source[property];}// 返回目标对象return target;
};var father = {money: 1E10,friends: ['Lee', 'Tom']
}
var son = {name: '张三'
}// son 继承 father
extend(son, father);son.friends.push('Lucy');son.money = 10;son.name = '小明';

多继承 (方式一)

在这里插入图片描述

// 多继承 属性复制  
var mix = function () {var i = 1,                      // 从第二个参数起为被继承的对象len = arguments.length,     // 获取参数长度target = arguments[0],      // 第一个对象为目标对象arg;                        // 缓存参数对象// 遍历被继承的对象for (; i < len; i++) {// 缓存当前对象arg = arguments[i];// 遍历被继承对象中的属性for (var property in arg) {// 将被继承对象中的属性复制到目标对象中target[property] = arg[property];}}// 返回目标对象return target;
};let parent1 = { money: 1E10 };
let parent2 = { friends: ['Lee', 'Tom'] };
let parent3 = { hobbies: ['躺着'] };
let son = { name: '小明' };mix(son, parent1, parent2, parent3);console.log(son);

多继承 (方式二)

在这里插入图片描述

Object.prototype.mix = function () {var i = 0,                      // 从第一个参数起为被继承的对象len = arguments.length,     // 获取参数长度arg;                        // 缓存参数对象// 遍历被继承的对象for (; i < len; i++) {// 缓存当前对象arg = arguments[i];// 遍历被继承对象中的属性for (var property in arg) {// 将被继承对象中的属性复制到目标对象中this[property] = arg[property];}}
}let parent1 = { money: 1E10 };
let parent2 = { friends: ['Lee', 'Tom'] };
let parent3 = { hobbies: ['躺着'] };
let son = { name: '小明' };
son.mix(parent1, parent2, parent3);
console.log(son);

多种调用方式-多态

多态,就是同一个方法多种调用方式

function Add() {// 无参数算法function zero() {return 10;}// 一个参数算法function one(num) {return 10 + num;}// 两个参数算法function two(num1, num2) {return num1 + num2;}// 相加共有方法this.add = function () {var arg = arguments,// 获取参数长度len = arg.length;switch (len) {// 如果没有参数case 0:return zero();// 如果只有一个参数case 1:return one(arg[0]);// 如果有两个参数case 2:return two(arg[0], arg[1]);}}
}
// 实例化类
var A = new Add();
//测试
console.log(A.add());       // 10
console.log(A.add(5));      // 15
console.log(A.add(6, 7));   // 13

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_398702.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二十一、JAVA调用存储过程(Oracle专栏)

2022年9月28日16:33:11目录 &#x1f3c6;一、存储过程的创建及调用 ⭐️1.1、PLSQL编程 ⭐️1.2、程序结构 ⭐️1.3、变量 1.3.1、普通变量 1.3.2、引用型变量 1.3.3、记录型变量 ⭐️1.4、流程控制 1.4.1、条件分支 1.4.2、循环 &#x1f3c6;二、游标 ⭐️2.1、…

网状神经系统的典型特点,网状结构神经系统

脑干网状结构对肌紧张既有抑制作用也有加强作用。 选择A对。理由如下&#xff1a;网状结构中存在有抑制和加强肌紧张和肌运动区域&#xff0c;分别成为抑制区和易化区。抑制区位于网状结构的腹内侧部分。易化区位于网状结构的背外侧、脑桥被盖、中脑中央灰质及被盖。 &#x…

什么是RFID技

什么是RFID技术 RFID射频识别是一种非接触式的自动识别技术&#xff0c;它通过射频信号自动识别目标对象并获取相关数据&#xff0c;识别无需人工干预&#xff0c;可工作于各种恶劣环境。RFID技术可识别高速运动物体并同时识别多个标签&#xff0c;操作快捷方便。 ​​​​​…

Bootstrap——flex布局(定义弹性盒子、排列方向、内容排列、项目对齐、自身对齐、自动对等、等宽变换、自动边距、包裹、排序、对齐内容)

Bootstrap4与Bootstrap3最大的区别是Bootstrap 4使用弹性盒子来布局&#xff0c;而不是使用浮动来布局。弹性盒子也是CSS的一种新的布局模式&#xff0c;更适合响应式的设计。 布局的传统解决方案,基于盒状模型&#xff0c;依赖display属性 position属性 float属性。它对…

dif分页、排序、过滤功能

分页功能 接口中只有查询全部数据接口有时候数据量非常大&#xff0c;所以需要用到分页功能&#xff0c;在rest_framework中提供了三种分页的方法 一.PageNumberPagination 第一步&#xff1a;定义一个分页类继承PageNumberPagination from rest_framework.pagination import P…

Day02 -尚品汇-路由传递参数

围绕这个开展 1》在Header.vue里面 2》在Header.vue里面 第一种方式&#xff1a;&#xff08;字符串形式写法&#xff09; 传递params参数 3》在index.js里面 【此处用的是params参数 需要占位】 4》在Header.vue里面 【params写法】 1--4的效果图 我还想加一个传…

NTFS文件系统详解(二)MBR\EBR基本信息

NTFS文件系统详解&#xff08;二&#xff09;MBR\EBR基本信息一、MBR结构分析1. 第一个分区表项2. 第二个分区表项3. 第三个分区表项4. 第四个分区表项二、EBR结构分析1. 第一个分区表项2. 第二个分区表项2.1 第一个分区表项2.2 第二个分区表项2.3 第三个分区表项系列文章目录经…

springBoot实验填报系统

摘要 国内教育行业的快速发展&#xff0c;人们为了能够更加方便地管理学生实验填报&#xff0c;实验填报系统被人们开发出来从而更好地方便管理学生实验填报&#xff0c;一个完美的实验填报系统已经成为各个学校的追求目标。 本系统利用SpringBoot技术进行开发实验填报系统是未…

asp.net旅游网站系统VS开发sqlserver数据库web结构c#编程计算机网页项目

一、源码特点 ASP.NET 旅游网站系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net旅游网站系统VS开发sqlserver数…

git基本使用方式整理

文章目录A:配置个人信息B:创建目录C:初始化仓库D:往仓库添加和提交文件E:状态查看命令F:版本回退G:对git占存区的理解H&#xff1a;管理修改I&#xff1a;撤销修改J&#xff1a;删除文件K:关联远程仓库L:仓库克隆在Git安装完成之后&#xff0c;需要配置Git连接的用户信息&#…

python与Electron联合编程记录之八(Hello Flask!)

Hello Flask&#xff01; 既然知道了Electron和Flask信息交换的原理&#xff0c;我们就可以开始进行Electron和Flask的联合编程了。   让我们紧接第三部分“Hello&#xff0c;Electron!”项目继续探索Flask的用法。 1、配置虚拟环境 由于Flask是python编写的&#xff0c;所以…

Python百日进阶-WEB开发】Day156 - 前端基础 之 BootStrap(一)

文章目录一、BootStrap的安装和使用1.1 BootStrap介绍1.2 BootStrap特点1.3 下载使用1.3.1 下载BootStrap:1.3.2 下载 jquery.js1.4 创建项目1.5 bootstrap和vue对比1.5.1 Bootstrap和vue不是一个层级的东西&#xff0c;Vue是框架&#xff0c;bootstrap是基于jQuery的组建库。1…

洛谷 T281315 掌控

PS&#xff1a;如果读过题了可以跳过题目描述直接到题解部分 提交链接&#xff1a;洛谷 T281315 掌控 题目 题目描述 公元 2044 年&#xff0c;人类进入了宇宙纪元。L 国有 nnn 个星球&#xff0c;分别编号为 111 到 nnn &#xff0c;每一星球上有一个球长。有些球长十分强大…

Ryu的安装+使用

ryu的安装 安装RYU&#xff0c;需要安装一些python的套件&#xff1a; python-eventlet python-routes python-webob python-paramiko 安装RYU主要有两种方式&#xff1a; 1、pip安装 pip install ryu git clone https://github.com/osrg/ryu.git cd ryu sudo pip install -…

【路径规划】基于matlab卡尔曼滤波、三次插值极速赛道赛车路径规划【含Matlab源码 2158期】

一、卡尔曼滤波路径追踪优化简介 割草机器人通过比对当前t时刻位置、导航方程之间偏移角度θ和偏移距离d,确定t1时刻的运动方向属于递推型路径追踪。割草机器人工作过程中受到地面起伏等环境因素影响,在采用上述追踪方法时会和预测值产生偏差,造成机器人偏离导航方程,称之为系…

数据大放送之HMA

一、前言 今天给大家带来的是空间分辨率为8米的DEM数据&#xff0c;可能有小伙伴会疑惑&#xff0c;是不是需要付费&#xff1f; 不用、不用、不用&#xff0c;完全免费。 也就是我们的HMA数据&#xff0c;全称NSIDC DAAC High Mountain Asia&#xff0c;也叫高山亚洲数据集…

Java:JSP是什么?Jakarta服务器页面介绍

Jakarta Server Pages(以前称为 JavaServer Pages)是一种 Java 标准技术&#xff0c;开发人员使用它来为 Java Web 应用程序编写动态的、数据驱动的网页。JSP 建立在 Java Servlet(又名 Jakarta Servlet)规范之上&#xff0c;是 Jakarta EE 中包含的用于持续支持和升级的 Java …

JPA的学习

JPA jpa详解 JPA是Java Persistence API的简称&#xff0c;中文名Java持久层API&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。 Spring Date整合jpa Spring Date pring Data是Spring的一个子项目…

超详细Redis入门教程!

一、引言 为啥需要redis?没有reids有啥问题?↓ 1.1 数据库压力过大 由于用户量增大&#xff0c;请求数量也随之增大&#xff0c;数据压力过大 1.2 数据不同步 多台服务器之间&#xff0c;数据不同步 1.3 传统锁失效 多台服务器之间的锁&#xff0c;已经不存在互斥性了 redis如…

(附源码)计算机毕业设计SSM志愿者服务平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…