当前位置: 首页 > news >正文

【JavaScript 16】对象继承 原型对象属性 原型链 构造函数属性 instanceof运算符 继承 多重继承 模块

对象继承

      • 原型对象概述
      • instanceof运算符
      • 构造函数的继承
      • 多重继承
      • 模块

A 对象通过继承 B 对象,就能 直接拥有 B 对象的所有属性和方法(利于代码复用)
大部分面向对象的编程语言都是通过类(class)实现对象的继承
传统上JavaScript 语言的继承不通过 class,而是通过**原型对象(prototype)**实现
ES6引入了基于class的继承

下面是JS原型链继承相关笔记

原型对象概述

1 构造函数缺点
JS通过构造函数生成新的对象
因此构造函数可以视为对象的模版(实例对象的属性和方法可以定义在构造函数内部)

function Cat (name, color) {this.name = name;this.color = color;
}var cat1 = new Cat('LH', 'White');
cat1.name // 'LH'
cat1.color // 'White' 

上面代码中Cat函数是一个构造函数,函数内部定义了name属性和color属性,所有实例对象(上例是cat1)都会生成这两个属性,即这两个属性会定义在实例对象上面

通过构造函数为实例对象定义属性,虽然很方便,但是有一个缺点是:
同一个构造函数的多个实例之间无法共享属性从而造成对系统资源的浪费

function Cat(name, color) {this.name = name;this.color = color;this.meow = function () {console.log('miao');};
}var cat1 = new Cat('LH', 'White');
var cat2 = new Cat('EH', 'Black');cat1.meow === cat2.meow
// false

上面代码中,cat1和cat2是同一个构造函数的两个实例都具有meow方法
由于meow方法是生成在每个实例对象上面,所以两个实例就生成了两次
也即每新建一个实例就会新建一个meow方法
这既没有必要,又浪费系统资源,因为所有meow方法都是同样的行为,完全应该共享
这种缺点的解决方法即是JS的原型对象(prototype)

2 prototype 属性作用

JS继承机制的设计思想是原型对象的所有属性和方法,都能被实例对象共享

也即若属性和方法定义在原型上则所有的实例对象都可以共享,从而节省内存并且体现实例对象之间的联系

下面是为对象指定原型
JS规定每个函数都有一个prototype属性用于指向一个对象

function f() {}
typeof f.prototype // "object"

上面代码中,函数f默认具有prototype属性,指向一个对象
对于普通函数来说,该属性基本无用
但是对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型

function Animal(name) {this.name = name;
}
Animal.prototype.color = 'white';var cat1 = new Animal('LH');
var cat2 = new Animal('EH');cat1.color // 'white'
cat2.color // 'white'

上面代码中构造函数Animal的prototype属性,就是实例对象cat1和cat2的原型对象
原型对象上添加一个color属性则实例对象都共享该属性

原型对象的属性不是实例对象自身的属性
只要修改原型对象,变动就立刻会体现在所有实例对象上

Animal.prototype.color = 'yellow';cat1.color // "yellow"
cat2.color // "yellow"

原型对象的color属性的值变为yellow,两个实例对象的color属性立刻跟着变了
这是因为实例对象其实没有color属性,都是读取原型对象的color属性
也就是说,当实例对象本身没有某个属性或方法的时候,它会到原型对象去寻找该属性或方法(否则直接使用本身的属性和方法)
这就是原型对象的美妙之处

cat1.color = 'black';cat1.color // 'black'
cat2.color // 'yellow'
Animal.prototype.color // 'yellow'

总结一下原型对象的作用,就是定义所有实例对象共享的属性和方法
这也是被称为原型对象的原因,而实例对象可以视作从原型对象衍生出来的子对象

Animal.prototype.walk = function () {console.log(this.name + ' is walking');
};

上面代码中Animal.prototype对象上面定义了一个walk方法,这个方法将可以在所有Animal实例对象上面调用

3 原型链
JavaScript 规定所有对象都有自己的原型对象(prototype)
一方面任何一个对象都可以充当其他对象的原型
另一方面由于原型对象也是对象,所以它也有自己的原型
由此形成一个原型链(prototype chain)

如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype(也即Object构造函数的prototype属性
所有对象都继承Object构造函数的prototype属性
这是所有对象都有valueOftoString方法的原因,因为都是从Object.prototype继承的

而Object.prototype对象的原型是null
null没有任何属性与方法也没有自己的原型
Object.getPrototypeOf方法返回参数对象的原型

Object.getPrototypeOf(Object.prototype)
// null

读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找
如果直到最顶层的Object.prototype还是找不到,则返回undefined

如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做覆盖(overriding)

注意一级级向上在整个原型链上寻找某个属性对性能是有影响的

举例来说,如果让构造函数的prototype属性指向一个数组,就意味着实例对象可以调用数组方法

var MyArray = function () {};MyArray.prototype = new Array();
MyArray.prototype.constructor = MyArray;var mine = new MyArray();
mine.push(1, 2, 3);
mine.length // 3
mine instanceof Array // true

上面代码中,mine是构造函数MyArray的实例对象
由于MyArray.prototype指向一个数组的实例使得mine可以调用数组方法(这些方法定义在数组实例的prototype对象上面)
最后那行instanceof表达式,用来比较一个对象是否为某个构造函数的实例,结果就是证明mine为Array的实例

4 constructor属性
prototype对象有constructor属性默认指向prototype对象所在的构造函数

function P() {}
P.prototype.constructor === P // true

由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承

function P() {}
var p = new P();p.constructor === P // true
p.constructor === P.prototype.constructor // true
p.hasOwnProperty('constructor') // false

上面代码中,p是构造函数P的实例对象,但是p自身没有constructor属性该属性其实是读取原型链上面的P.prototype.constructor属性

constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的

function F() {};
var f = new F();f.constructor === F // true
f.constructor === RegExp // false 

上面代码中constructor属性确定了实例对象f的构造函数是F,而不是RegExp

此外由于constructor属性我们可以从一个实例对象新建另一个实例

function Constr() {}
var x = new Constr();var y = new x.constructor();
y instanceof Constr // true

上面代码中x是构造函数Constr的实例,可以从x.constructor间接调用构造函数
这也使得在实例方法中调用自身的构造函数成为可能

Constr.prototype.createCopy = function () {return new this.constructor();
};

上面代码createCopy方法调用构造函数新建另一个实例

constructor属性表示原型对象构造函数之间的关联关系
如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错

function Person(name) {this.name = name;
}Person.prototype.constructor === Person // truePerson.prototype = {method: function () {}
};Person.prototype.constructor === Person // false
Person.prototype.constructor === Object // true

上面代码中,构造函数Person的原型对象改掉了,但是没有修改constructor属性
导致这个属性不再指向Person
由于Person的新原型是一个普通对象,而普通对象的constructor属性指向Object构造函数
导致Person.prototype.constructor变成了Object

修改原型对象时,一般要同时修改constructor属性的指向

// 坏的写法
C.prototype = {method1: function (...) { ... },// ...
};// Zane的写法
C.prototype = {constructor: C,method1: function (...) { ... },// ...
};// 更好的Zane写法
C.prototype.method1 = function (...) { ... };

如果不能确定constructor属性是什么函数,还有一个办法:通过name属性,从实例得到构造函数的名称

funciton Foo() {};
var f = new Foo();
f.constructor.name // "Foo"

instanceof运算符

instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例

var v = new Vehicle();
v instanceof Vehicle // true

instanceof运算符的左边是实例对象,右边是构造函数
instanceof检查右边构造函数的原型对象(prototype),是否在左边对象的原型链上
下面两种写法等价

v instanceof Vehicle
// 等同于
Vehicle.prototype.isPrototypeOf(v)

上面代码中,Vehicle是对象v的构造函数,它的原型对象是Vehicle.prototype
isPrototypeOf()方法是 JavaScript 提供的原生方法,用于检查某个对象是否为另一个对象的原型

由于instanceof检查整个原型链,因此同一个实例对象,可能会对多个构造函数都返回true

var d = new Date();
d instanceof Date // true
d instanceof Object // true

由于任意对象(除了null)都是Object的实例,所以instanceof运算符可以判断一个值是否为非null的对象

有一种特殊情况,就是左边对象的原型链上,只有null对象。这时,instanceof判断会失真

var obj = Object.create(null);
typeof obj // "object"
obj instanceof Object // false

上面代码中,Object.create(null)返回一个新对象obj,它的原型是null
右边的构造函数Object的prototype属性,不在左边的原型链上,因此instanceof就认为obj不是Object的实例
这是唯一的instanceof运算符判断会失真的情况

instanceof运算符的一个用处是判断值的类型

var x = [1, 2, 3];
var y = {};
x instanceof Array // true
y instanceof Object // true

上面代码中instanceof运算符判断,变量x是数组,变量y是对象
注意,instanceof运算符只能用于对象,不适用原始类型的值
此外,对于undefined和null,instanceof运算符总是返回false。

var s = 'hello';
s instanceof String // falseundefined instanceof Object // false
null instanceof Object // false

上面代码中,字符串不是String对象的实例(因为字符串不是对象),所以返回false

利用instanceof运算符,还可以巧妙地解决,调用构造函数时,忘了加new命令的问题

function Fubar(foo, bar) {if (this instanceof Fubar) {this._foo = foo;this._bar = bar;} else {return new Fubar(foo, bar);}
}

上面代码使用instanceof运算符,在函数体内部判断this关键字是否为构造函数Fubar的实例
如果不是就表明忘了加new命令

构造函数的继承

构造函数的继承是非常常见的需求(分为两步)

第一步是在子类构造函数中调用父类构造函数

function Sub(value) {Super.call(this);this.prop = value;
}

上面代码中,Sub是子类的构造函数,this是子类的实例
在实例上调用父类的构造函数Super,就会让子类实例具有父类实例的属性

第二步是让子类的原型指向父类的原型(子类继承父类原型)

Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.prototype.method = '...';

上面代码中,Sub.prototype是子类的原型,要将它赋值为Object.create(Super.prototype),而不是直接等于Super.prototype
否则后面两行对Sub.prototype的操作,会连父类的原型Super.prototype一起修改

另外还可以写成Sub.prototype等于一个父类实例

Sub.prototype = new Super();

上面这种写法也有继承的效果,但是子类会具有父类实例的方法
有时这可能不是我们需要的,所以不推荐使用这种写法

举个栗子

function Shape() {this.x = 0;this.y = 0;
}Shape.prototype.move = function (x, y) {this.x += x;this.y += y;console.info('Shape moved');
};

让Rectangle构造函数继承Shape

// 1. 子类继承父类实例
function Rectangle() {Shape.call(this); // 调用父类构造函数
}
// or
function Rectangle() {this.base = Shape;this.base();
}// 2. 子类继承父类原型
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

采用这样的写法以后,instanceof运算符会对子类和父类的构造函数都返回true

var rect = new Rectangle();rect instanceof Rectangle // true
rect instanceof Shape // true

上面代码中,子类是整体继承父类
有时只需要单个方法的继承可以采用下面的写法

ClassB.prototype.print = function() {ClassA.prototype.print.call(this);// some code
}

上面代码中子类B的print方法先调用父类A的print方法再部署自己的代码
这就等于继承了父类A的print方法

多重继承

JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象
但是可以通过变通方法实现这个功能

function M1() {this.hello = 'hello';
}function M2() {this.world = 'world';
}function S() {M1.call(this);M2.call(this);
}// 继承 M1
S.prototype = Object.create(M1.prototype);
// 继承链上加入 M2
Object.assign(S.prototype, M2.prototype);// 指定构造函数
S.prototype.constructor = S;var s = new S();
s.hello // 'hello'
s.world // 'world'

上面代码中子类S同时继承了父类M1和M2
这种模式又称为 Mixin(混入)

模块

随着网站逐渐变成互联网应用程序,嵌入网页的 JavaScript 代码越来越庞大复杂
网页越来越像桌面程序,需要一个团队分工协作进度管理单元测试等等,开发者必须使用软件工程的方法管理网页的业务逻辑

这就需要JS的模块化编程
在理想的情况下开发者只需要实现核心的业务逻辑而其他都可以加载他人写好的模块
但是JS刚开始不是一种模块化编程语言,到ES6才开始支持类和模块
下面是使用传统方法利用对象实现模块效果

1 基本实现
模块是实现特定功能的一组属性和方法的封装
简单的做法是把模块写成一个对象,所有的模块成员都放到这个对象里面

var module1 = new Object({_count : 0,m1 : function () {// ...},m2 : function () {// ...}
});

上面的函数m1和m2都封装在module1对象中
使用时直接调用该对象的属性

module1.m1();

但是这样的写法会暴露所有模块成员,内部状态可以被外部改写
比如外部代码可以直接改变内部计数器的值

module1._count = 5;

2 封装私有变量:构造函数写法
使用构造函数封装私有变量

function StringBuilder() {var buffer = [];this.add = function (str) {buffer.push(str);};this.toString = function () {return buffer.join('');};
}

上面代码中buffer是模块的私有变量
一旦生成实例对象,外部是无法直接访问buffer的
但是这种方法将私有变量封装在构造函数中,导致构造函数与实例对象是一体的,总是存在于内存之中,无法在使用完成后清除
这意味着构造函数有双重作用,既用来塑造实例对象,又用来保存实例对象的数据,违背了构造函数与实例对象在数据上相分离的原则
即实例对象的数据,不应该保存在实例对象以外
同时耗费内存

function StringBuilder() {this._buffer = [];
}StringBuilder.prototype = {constructor: StringBuilder,add: function (str) {this._buffer.push(str);},toString: function () {return this._buffer.join('');}
};

这种方法将私有变量放入实例对象中,好处是看上去更自然,但是它的私有变量可以从外部读写,不是很安全

3 封装私有变量:IIFE写法
使用IIFE(Immediately-Invoked Function Expression)
将相关属性和方法封装在一个函数作用域中从而不暴露私有成员

var module1 = (function () {var _count = 0;var m1 = function () {// some code};var m2 = function () {// some code};return {m1: m1,m2: m2};
})();

使用上面的方法外部代码无法读取内部的_count变量

console.info(module1._count); // undefined

上面的module1就是 JavaScript 模块的基本写法

下面是对该模块写法的优化

4 模块的放大模式
如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用放大模式(augmentation)

var module1 = (function (mod) {mod.m3 = function () {// ...};return mod;
})(module1);

上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块

在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载
如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用宽放大模式(Loose augmentation)

var module1 = (function (mod) {// ...return mod;
})(window.module1 || {});

与放大模式相比,宽放大模式就是立即执行函数的参数可以是空对象

5 输入全局变量
独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互
为了在模块内部调用全局变量,必须显式地将其他变量输入模块

var module1 = (function ($, YAHOO) {// ...
})(jQuery, YAHOO);

上面的module1模块需要使用 jQuery 库和 YUI 库,就把这两个库(其实是两个模块)当作参数输入module1
这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显

立即执行函数还可以起到命名空间的作用

(function($, window, document) {function go(num) {}function handleEvents() {}function initialize() {}function dieCarouselDie() {}// attach to the global scopewindow.finalCarousel = {init : initialize,destroy: dieCarouselDie}})( jQuery, window, document );

上面代码中,finalCarousel对象输出到全局
对外暴露init和destroy接口,内部方法go、handleEvents、initialize、dieCarouselDie都是外部无法调用的

相关文章:

【JavaScript 16】对象继承 原型对象属性 原型链 构造函数属性 instanceof运算符 继承 多重继承 模块

对象继承 原型对象概述instanceof运算符构造函数的继承多重继承模块 A 对象通过继承 B 对象,就能 直接拥有 B 对象的所有属性和方法(利于代码复用) 大部分面向对象的编程语言都是通过类(class)实现对象的继承 但 传统…...

地下管线三维自动建模软件MagicPipe3D V3.0发布

2023年9月1日经纬管网建模系统MagicPipe3D V3.0正式发布,该版本经过众多用户应用和反馈,在三维地下管线建模效果、效率、适配性等方面均有显著提升!MagicPipe3D本地离线参数化构建地下管网模型(包括管道、接头、附属设施等&#x…...

百度等8家企业首批上线大模型服务;大语言模型微调之道

🦉 AI新闻 🚀 百度等8家企业首批上线大模型服务 摘要:百度、字节、中科院旗下8家企业/机构的大模型通过备案,正式面向公众提供服务。百度旗下AI大模型产品文心一言率先开放,用户可下载App或登录官网体验。百川智能也…...

二、Mycat2 相关概念及读写分离

第三章 Mycat2 相关概念 3.1 概念描述 1、分库分表 按照一定规则把数据库中的表拆分为多个带有数据库实例,物理库,物理表访问路 径的分表。 解读:分库:一个电商项目,分为用户库、订单库等等。 分表:一张订单表数据数百万&#xff…...

react利用wangEditor写评论和@功能

先引入wangeditor写评论功能 import React, { useEffect, useState, useRef, forwardRef, useImperativeHandle } from react; import wangeditor/editor/dist/css/style.css; import { Editor, Toolbar } from wangeditor/editor-for-react; import { Button, Card, Col, For…...

Android之布局转圆角

Android之布局转圆角 文章目录 Android之布局转圆角说明一、效果图二、实现步骤1.自定义RoundRelativeLayout2.使用 总结 说明 很多需求比较无语,需要某个布局转圆角,像个显眼包一样,所以为了满足显眼包,必须整呐提示&#xff1a…...

Linux的目录结构特点

Linux的目录结构特点 1、使用树形目录结构来组织和管理文件。 2、整个系统只有一个根目录(树根),Linux的根目录用“/”表示。 3、其他所有分区以及外部设备(如硬盘,光驱等)都是以根目录为起点&#xff0…...

【算法与数据结构】654、LeetCode最大二叉树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树这两道题有些类似,相关代…...

您必须尝试的 4 种经典特征提取技术!

一、说明 特征提取如何实现?其手段并不是很多,有四个基本方法,作为AI工程师不能不知。因此,本篇将对四种特征提取给出系统的方法。 二、概述 图像分类长期以来一直是计算机视觉领域的热门话题,并希望能够保持这种状态。…...

Unity中Shader的遮罩的实现

文章目录 前言一、遮罩效果的实现主要是使用对应的纹理实现的,在属性中暴露对应的遮罩纹理,对其进行采样后,最后相乘输出即可二、如果需要像和主要纹理一样流动,则需要使用和_Time篇一样的方法实现流动即可 前言 Unity中Shader的…...

架构师成长之路|Redis key过期清除策略

Eviction policies maxmemory 100mb 当我们设置的内存达到指定的内存量时,清除策略的配置方式决定了默认行为。Redis可以为可能导致使用更多内存的命令返回错误,也可以在每次添加新数据时清除一些旧数据以返回到指定的限制。 当达到最大内存限制时,Redis所遵循的确切行为是…...

ubuntu20.04使用privoxy进行http代理转http代理,并定制http代理头(hide-user-agent的使用方法)

#sudo apt-get update;sudo apt install -y privoxy #sudo apt remove privoxyprivoxy --version; rootfv-az1239-825:/tmp# privoxy --version Privoxy version 3.0.28 (https://www.privoxy.org/) rootfv-az1239-825:/tmp# 安装完毕后,先停止服务,修改配置文件,再启动服…...

任意文件读取

文章目录 渗透测试漏洞原理任意文件读取1. 任意文件读取概述1.1 漏洞成因1.2 漏洞危害1.3 漏洞分类1.4 任意文件读取1.4.1 文件读取1.4.2 任意文件读取1.4.3 权限问题 1.5 任意文件下载1.5.1 一般情况1.5.2 PHP实现1.5.3 任意文件下载 2. 任意文件读取攻防2.1 路径过滤2.1.1 过…...

微信小程序餐饮外卖系统设计与实现

摘 要 随着现在的“互联网”的不断发展。现在传统的餐饮业也朝着网络化的方向不断的发展。现在线上线下的方式来实现餐饮的获客渠道增加,可以更好地帮助餐饮企业实现更多、更广的获客需求,实现更好的餐饮销售。截止到2021年末,我国的外卖市场…...

一文速览嵌入式六大出口

嵌入式行业的前景确实十分广阔,并且在许多领域都发挥着重要作用。以下是一些关键点,说明嵌入式系统的发展潜力和前途: 1. 物联网(IoT):嵌入式系统是实现智能家居、智能城市、智能工厂等物联网设备的核心。物…...

华为云云服务器评测 | 宝塔8.0镜像应用

目录 🍒写在前面 🍒产品优势 🍒购买服务器 🍒服务器配置 🍒登录宝塔页面 🦐博客主页:大虾好吃吗的博客 🦐专栏地址:闲谈专栏地址 写在前面 云耀云服务器L实例是新一代开箱…...

构建简单的Node.js HTTP服务器,发布公网远程访问的快速方法

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…...

ModaHub魔搭社区:向量数据库产业的现状与技术挑战

I. 向量数据库的崛起 什么是向量数据库 在过去的一段时间里,向量数据库逐渐在数据库领域崭露头角。那么,什么是向量数据库呢?简单来说,向量数据库是一种专门设计用来处理向量数据的数据库。这些向量数据可以是物理测量、机器学习模型输出、地理空间数据等。向量数据库使用…...

pmp和软件高项哪个含金量高?

人们常将PMP和高项放在一起比较,因为这两种证书都适用于项目经理职位,它们有高达60%的知识点重合度。在决定考哪一种证书之前,人们常常会感到困惑。 下面看一下pmp和软考高项的差异。 发证机构不同 PMP(Project Management Professional)是…...

手把手教你用Vite构建第一个Vue3项目

写在前面 在之前的文章中写过“如何创建第一个vue项目”,但那篇文章写的是创建vue2的 项目。 传送门如何创建第一个vue项目 打开Vue.js官网:https://cn.vuejs.org/,我们会发现Vue 2 将于 2023 年 12 月 31 日停止维护 虽然Vue2的项目还不少&#xff0…...

美创科技获通信网络安全服务能力评定(应急响应一级)认证!

近日,中国通信企业协会公布通信网络安全服务能力评定2023年第一批获证企业名单。 美创科技获得应急响应一级资质,成为2023年第一批获证企业之一! 通信网络安全服务能力评定是对通信网络安全服务单位从事通信网络安全服务综合能力的评定&#…...

计算机视觉与人工智能在医美人脸皮肤诊断方面的应用

一、人脸皮肤诊断方法 近年来,随着计算机技术和人工智能的不断发展,中医领域开始逐渐探索利用这些先进技术来辅助面诊和诊断。在皮肤望诊方面,也出现了一些现代研究,尝试通过图像分析技术和人工智能算法来客观化地获取皮肤相关的…...

RCU501 RMP201-8 KONGSBERG 分布式处理单元

RCU501 RMP201-8 KONGSBERG 分布式处理单元 AutoChief600使用直接安装在主机接线盒中的分布式处理单元。进出发动机的所有信号都在双冗余CAN线路(发动机总线)上传输。 所有不重要的传感器都可以与K-Chief 600报警和监控系统共享,只需要一个主机接口。这一原则大大…...

说说 MVCC 的工作原理?

分析&回答 多版本并发控制(MVCC) InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现。这两个列,一个保存了行的创建时间,一个保存行的删除时间,并不是实际的时间,而是系统版本号。每开始一个新的事务&am…...

微信小程序请求接口返回的二维码(图片),本地工具和真机测试都能显示,上线之后不显示问题

请求后端接口返回的图片&#xff1a; 页面展示&#xff1a; 代码实现&#xff1a; :show-menu-by-longpress"true" 是长按保存图片 base64Code 是转为base64的地址 <image class"code" :src"base64Code" alt"" :show-menu-by-long…...

Python小知识 - 1. Python装饰器(decorator)

Python装饰器&#xff08;decorator&#xff09; Python装饰器是一个很有用的功能&#xff0c;它可以让我们在不修改原有代码的情况下&#xff0c;为已有的函数或类添加额外的功能。 常见的使用场景有&#xff1a; a. 函数缓存&#xff1a;对于一些计算量较大的函数&#xff0c…...

如何访问GitHub

1、手动修改hosts 1.1、查找到最新的GitHub的hosts信息 通过链接&#xff1a;https://raw.hellogithub.com/hosts 进行查找最新的GitHub的hosts信息 1.2、查找到hosts文件位置 先找到 hosts 文件的位置&#xff0c;不同操作系统&#xff0c;hosts 文件的存储位置也不同&…...

【广州华锐互动】智能变电站AR仿真实训系统大大提高培训的效率和质量

随着电力行业的不断发展&#xff0c;变电站的建设和运维变得越来越重要。传统的变电站运维培训方式存在着诸多问题&#xff0c;如难以真实模拟变电站运行环境、信息传递不及时、难以掌握实际操作技能等问题。而智能变电站AR仿真实训系统可以为变电站运维人员带来全新的培训方式…...

手写Mybatis:第11章-流程解耦,封装结果集处理器

文章目录 一、目标&#xff1a;结果集处理器二、设计&#xff1a;结果集处理器三、实现&#xff1a;结果集处理器3.1 工程结构3.2 结果集处理器关系图3.3 出参参数处理3.3.1 结果映射Map3.3.2 结果映射封装3.3.3 修改映射器语句类3.3.4 映射构建器助手3.3.5 语句构建器调用助手…...

金融风控数据分析-信用评分卡建模(附数据集下载地址)

本文引用自&#xff1a; 金融风控&#xff1a;信用评分卡建模流程 - 知乎 (zhihu.com) 在原文的基础上加上了一部分自己的理解&#xff0c;转载在CSDN上作为保留记录。 本文涉及到的数据集可直接从天池上面下载&#xff1a; Give Me Some Credit给我一些荣誉_数据集-阿里云…...