js构造函数和原型对象,ES6中的class,四种继承方式

一、构造函数

1.构造函数是一种特殊的函数,主要用来初始化对象
2.使用场景

常见的{...}语法允许创建一个对象。可以通过构造函数来快速创建多个类似的对象

 const Peppa = {name: '佩奇',age: 6,sex: '女'}const George = {name: '乔治',age: 3,sex: '男'}const Mum = {name: '佩奇妈妈',age: 30,sex: '女'}const Dad = {name: '佩奇爸爸',age: 32,sex: '男'}function Pig(name, age, sex) {this,name = name;this.age = age;this.sex = sex;}const Peppa1 = new Pig('佩奇', 6, '女')const George1 = new Pig('乔治', 3, '男')const Mum1 = new Pig('佩奇妈妈', 30, '女')const Dad1 = new Pig('佩奇爸爸', 32, '男')

构造函数在技术上是常规函数

命名以大写字母开头。

通过new关键字来执行。

3.创建构造

使用new关键字调用函数的行为被称为实例化

实例化构造函数时没有参数可以省略()

构造函数内部无需写return,返回值即为新创建的对象

构造函数内部的return返回的值无效,所以不需要写return

new Object()和new Date()也是实例化的构造函数

4.实例化执行过程!

a.创建新空对象,

b.构造函数this指向新对象,

c.执行构造函数代码,修改this,添加新的属性,

d.返回新对象

5.实例成员和静态成员

实例成员:通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)

为构造函数传入参数,创建结构相同但值不同的对象

构造函数创建的实例对象彼此独立互不影响

    //实例对象上的属性和方法属于实例成员function Pig(name) {this.name = name;}const peiqi = new Pig('佩奇')const qiaozhi = new Pig('乔治')peiqi.name = '小猪佩奇' //实例属性peiqi.sayHi = () => { //实例方法console.log('hi~');}console.log('peiqi', peiqi);console.log('qiaozhi', qiaozhi);

构造函数的属性和方法称为静态成员(静态属性和静态成员)

静态成员只能通过构造函数来访问

静态方法中的this指向构造函数

    //构造函数上的属性和方法称为静态成员function Pig(name) {this.name = name;}Pig.eyes = 2 //静态属性console.log('Pig.eyes', Pig.eyes);Pig.sayHi = function() { //静态方法console.log(this);}console.log('Pig.sayHi', Pig.sayHi);

6.内置构造函数

引用类型Object,Array,RegExp,Date等

包装类型String,Number,Boolean等

Object的静态方法Object.keys(),Object.values(),Object.assign()

    const o = {name: '佩奇',age: 6}//获取所有属性名,返回数组console.log(Object.keys(o));//获取所有属性值,返回数组console.log(Object.values(o));//拷贝对象const oo = {}Object.assign(oo, o)//给对象添加属性console.log(oo);Object.assign(o, {gender: '女'})console.log(o);

二、编程思想

1.面向过程

分析解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用。按照分析好了的步骤,按照步骤解决问题。

优点:性能比面向对象高,适合和硬件联系很紧密的东西

缺点:没有面向对象易维护、易复用、易扩展

2.面向对象

把食物分解成一个一个对象,然后由对象之间分工与工作。

以功能来划分问题,而不是步骤。

面向对象编程(oop):在面向对象程序开发中,每一个对象都是功能中心,具有明确分工。面向对象编程具有灵活,代码可复用,容易维护和开发的优点,更适合多人合作的大型软件项目。

优点:封装性,继承性,多态性。可以使系统更加灵活,更加易于维护

缺点:性能比面向过程低

js实现面向对象需要借助构造函数来实现

构造函数实例创建的对象彼此独立,互不影响。

构造函数存在浪费性能的问题
    function Star(name, age, sex) {this.name = name;this.age = age;this.sing = function() {console.log('sing');};}const ldh = new Star('ldh', 55)const zxy = new Star('zxy', 58)console.log(ldh.sing === zxy.sing); //false

三、原型

原型可以解决构造函数里浪费内存的问题。

1.目的:能够利用原型对象实现方法共享

构造函数通过原型分配的函数是所有对象所共享的。

js规定:每一个构造函数都有一个prototype属性,指向另一个对象,我们也称为原型对象。

这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存。

我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

    function Star(name, age, sex) {//公共属性写到构造函数里this.name = name;this.age = age;}const ldh = new Star('ldh', 55)const zxy = new Star('zxy', 58)console.log('Star.prototype', Star.prototype)//构造函数有一个prototype属性,公共方法写到原型对象身上Star.prototype.sing = function() {console.log('唱歌');};ldh.sing()zxy.sing()console.log(ldh.sing === zxy.sing); //true

构造函数和原型对象中的this都指向实例化对象。

    let a;let b;function Star(name, age, sex) {a = this;this.name = name;this.age = age;}const ldh = new Star('ldh', 55)console.log(a === ldh);//true//构造函数里面的 this就是实例对象Star.prototype.sing = function() {b = this;console.log('唱歌');};ldh.sing()console.log(b === ldh);//true
    //自己定义数组扩展方法max,min,sumArray.prototype.max = function() {//原型函数里面的this指向实例化对象arrreturn Math.max(...this)}Array.prototype.min = function() {//原型函数里面的this指向实例化对象arrreturn Math.min(...this)}Array.prototype.sum = function() {//原型函数里面的this指向实例化对象arrreturn this.reduce((sum, item) => sum + item, 0)}const arr = [1, 2, 3]console.log(arr.max());console.log(arr.min());console.log(arr.sum());
2.constructor属性

每个原型对象里面都有一个constructor属性,该属性指向该原型对象的构造函数.

    function Star() {}const ldh = new Star()console.log(Star.prototype.constructor === Star);//true

 如果有多个对象的方法,我们可以给原型对象采取对象形式赋值。

但是这样就会覆盖构造函数原型对象原来的内容,修改后原型对象constructor就不再指向当前构造函数了,我们需要在修改后的原型对象中,添加一个constructor指向原来的构造函数。

    function Star() {}// Star.prototype.sing = function() {//     console.log('唱歌');// }// Star.prototype.dance = function() {//         console.log('跳');//     }Star.prototype = {//重新指回创造这个原型对象的构造函数constructor: Star,sing: function() {console.log('唱歌');},dance: function() {console.log('跳');}}console.log(Star.prototype);

 

3.原型

在每个对象都会有一个__proto_指向构造函数的prototype原型对象,之所以我们可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto_原型存在。

__protp_是js非标准属性,[prototype]和__protp_意义相同

用来表明当前实例对象指向哪个原型对象prototype

__protp_对象原型里面也有一个constructor属性,指向创建该实例对象的构造函数。

    function Star() {}const ldh = new Star()//每一个构造函数都有一个prototype属性,指向另一个对象,我们也称为原型对象。console.log('Star.prototype', Star.prototype);//每个原型对象里面都有一个constructor属性,该属性指向该原型对象的构造函数.console.log(Star.prototype.constructor === Star);//true//ldh.__proto__ 指向该构造函数的原型对象console.log(ldh.__proto__ === Star.prototype); //true//对象原型里面也有constructor属性,指向创建该实例对象的构造函数。console.log(ldh.__proto__.constructor === Star); //true

总结

prototype是原型对象,构造函数都自动有原型对象

construvtor属性在原型对象(prototype)和对象原型(__proto__)上都有 ,指向创建实例对象/原型的构造函数。

__proto__属性在实例对象里面,指向原型对象。

4.原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,js中大多是借助原型对象实现继承的特性。

    const Person = {head: 1,eyes: 2}function Woman() {}//Woman通过原型来继承PersonWoman.prototype = Person//指回原来的构造函数Woman.prototype.constructor = Womanconst red = new Woman()console.log('red', red);

问题:同时使用了同一个对象,根据引用类型的特点,他们指向同一个对象,修改一个都会改变。

const Person = {head: 1,eyes: 2}function Woman() {}Woman.prototype = PersonWoman.prototype.constructor = WomanWoman.prototype.sing = function() {console.log('唱歌');}const red = new Woman()console.log('red', red);function Man() {}Man.prototype = PersonMan.prototype.constructor = Manconst bob = new Man()console.log('bob', bob);

    function Person() {this.head = 1this.eyes = 2}function Woman() {}//父构造函数(父类)子构造函数(子类) 子类的原型=new父类Woman.prototype = new Person()Woman.prototype.constructor = WomanWoman.prototype.sing = function() {console.log('唱歌');}const red = new Woman()console.log('red', red);function Man() {}Man.prototype = new Person()Man.prototype.constructor = Manconst bob = new Man()console.log('bob', bob);

5.原型链

基于原型对象的继承使得不同的构造函数的原型对象关联在一起,并且这种关联的关系是一种链状结构,我们将原型对象的链状结构关系称为原型链。

    function Person() {}const ldh = new Person()console.log(ldh.__proto__);console.log(Person.prototype);console.log(ldh.__proto__ === Person.prototype); //trueconsole.log(Person.prototype.__proto__ === Object.prototype); //trueconsole.log(Object.prototype.__proto__); //nullconsole.log(ldh instanceof Person); //trueconsole.log(ldh instanceof Object); //true

原型链查找规则

a.当访问一个对象的属性时,首先查找这个对象自身有没有该属性。

b.如果没有就查找它的原型,也就是__proto__指向的prototype原型对象。

c.如果没有找到就查找原型对象的原型。

d.依次类推一直找到Object为之。

e.__proto__对象原型的意义就在于为对象成员查找机制提供一个方向。

f.可以使用instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上

四、示例

1.封装模态框 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><button id="delete">删除</button><button id="login">登录</button>
</body>
</html><script>//构造函数封装模态框function Modal(title = '', message = '') {// 1.创建div标签// 2.给div标签添加类名modal// 3.modal盒子内部填充2个div并且修改文字内容this.modalBox = document.createElement('div')this.modalBox.className = "modal"this.modalBox.innerHTML = `<div class="header">${title}<i>x</i></div><div class="main">${message}</div>`}//挂载open方法Modal.prototype.open = function() {//准备open显示时先判断 页面中有没有modal,有就移除,没有就添加const box = document.querySelector('.modal')box && box.remove()document.body.append(this.modalBox)//等盒子显示出来,就可以绑定关闭事件this.modalBox.querySelector('i').addEventListener('click', () => {//需要用箭头函数,这个this指向实例对象this.close()})}Modal.prototype.close = function() {this.modalBox.remove()}document.querySelector('#delete').addEventListener('click', () => {const del = new Modal('温馨提示', '你没有权限删除')del.open()})document.querySelector('#login').addEventListener('click', () => {const login = new Modal('友情提示', '你没有注册')login.open()})
</script>
 2.选项卡(构造函数写法)

 

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box div,#box1 div {width: 200px;height: 50px;background-color: palegreen;display: none;}.active {background-color: palevioletred;}#box .current,#box1 .current {display: block;background-color: palegreen;}</style>
</head><body><div id="box"><section><button class="active">娱乐</button><button>体育</button><button>教育</button></section><section><div class="current">娱乐</div><div>体育</div><div>教育</div></section></div><hr><div id="box1"><section><button class="active">娱乐</button><button>体育</button><button>教育</button></section><section><div class="current">娱乐</div><div>体育</div><div>教育</div></section></div>
</body>
<script>//构造函数function Tab(ele, type) {this.ele = document.querySelector(ele); // {ele:"元素"}this.btns = this.ele.children[0].childrenthis.divs = this.ele.children[1].childrenthis.changeColor(type); // 函数的调用  "click"}Tab.prototype.changeColor = function(type) {// this: 指向的是实例化对象的thisfor (let i = 0; i < this.btns.length; i++) {this.btns[i].addEventListener(type, () => {console.log(2);// this.btns[i]:i就可以用了,this.btns[i]代表具体点击的元素for (var j = 0; j < this.btns.length; j++) {this.btns[j].classList.remove("active")this.divs[j].classList.remove("current")}this.btns[i].classList.add("active")this.divs[i].classList.add("current")})}}// 创建对象let tab1 = new Tab("#box", "click")let tab2 = new Tab("#box1", "mouseover")</script></html>

 

五、class类

从ES6开始,JavaScript引入了类(class)的语法,可以用来创建构造函数。这种语法更加简洁和清晰。

    //写法一: 构造函数function Person(name, age) {this.name = name;   this.age = age;   }Person.prototype.say = function () {console.log("呵呵");}let p1 = new Person("zs", 10)let p2 = new Person("zs", 10)console.log(p1);console.log(p1 == p2); // false//写法二: class类的写法class Person {constructor(name, age) {this.name = name;this.age = age;}//相当于挂载在了构造函数的原型对象上, Person.prototype.say = function(){}say() {  console.log("呵呵");}}let p1 = new Person("zs", 10)let p2 = new Person("zs", 10)console.log(p1);console.log(p1 == p2); // false
选项卡(class类写法) 

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box div,#box1 div {width: 200px;height: 50px;background-color: palegreen;display: none;}.active {background-color: palevioletred;}#box .current,#box1 .current {display: block;background-color: palegreen;}</style>
</head><body><div id="box"><section><button class="active">娱乐</button><button>体育</button><button>教育</button></section><section><div class="current">娱乐</div><div>体育</div><div>教育</div></section></div><hr><div id="box1"><section><button class="active">娱乐</button><button>体育</button><button>教育</button></section><section><div class="current">娱乐</div><div>体育</div><div>教育</div></section></div>
</body>
<script>// class类class Tab {constructor(ele, type) {this.ele = document.querySelector(ele); // {ele:"元素"}this.btns = this.ele.children[0].childrenthis.divs = this.ele.children[1].childrenthis.changeColor(type); // 函数的调用  "click"}changeColor(type) {for (let i = 0; i < this.btns.length; i++) {this.btns[i].addEventListener(type, () => {console.log(2);// this.btns[i]:i就可以用了,this.btns[i]代表具体点击的元素for (var j = 0; j < this.btns.length; j++) {this.btns[j].classList.remove("active")this.divs[j].classList.remove("current")}this.btns[i].classList.add("active")this.divs[i].classList.add("current")})}}}let tab1 = new Tab("#box", "click")let tab2 = new Tab("#box1", "mouseover")
</script></html>

 六、继承

      发生在两个构造函数之间,如果说A构造函数使用了B构造函数中的属性或者方法,A继承自B,B就属于父类,A属于子类

      可以把构造函数当成一个类

1.借用父类构造函数继承

优点:可以继承父类构造函数内的属性和方法 ​ 缺点:不可以继承父类原型对象上的属性和方法

    // 定义父类构造函数function Father(name, age) {this.name = name;this.age = age;}// 父类原型方法Father.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);};// 定义子类构造函数function Child(name, age, grade) {// 借用父类构造函数Father.call(this, name, age); // 通过call()借用父类构造函数this.grade = grade; // 子类特有的属性}// 使用示例const child = new Child('Alice', 10, 5); //{name: 'Alice', age: 10, grade: 5}child.sayHello(); //  child.sayHello is not a function
2.原型链继承

优点:可以继承父类原型对象上的属性和方法 ​ 缺点:不可以继承父类构造函数内的属性和方法

 

    // Father类function Father(money) {this.money = money}Father.prototype.smoke = function() {console.log("吸烟");}// Son类function Son(name, money) {this.name = name;}Son.prototype = new Father(); // 会覆盖掉Son构造函数原型对象的constructor属性Son.prototype.constructor = Son; // 手动加上Son.prototype.study = function() {console.log("study");}var f = new Father(10000)var s = new Son("小张")console.log(s);s.smoke();
 3.组合继承

优点:实现函数复用,保证每个实例之间的属性不会相互影响。 ​

缺点:使用了两次继承,代码书写繁琐,还出现了constructor的覆盖

    // Father类function Father(money) {this.money = money}Father.prototype.smoke = function() {console.log("吸烟");}// Son类function Son(name, money) {this.name = name;Father.call(this, money); // 继承父类属性的关键}Son.prototype = new Father(); // 继承父类原型对象方法的关键Son.prototype.study = function() {console.log("study");}var s = new Son("小张", 1000); // 即继承了属性console.log(s);s.smoke(); // 又继承了父类原型对象上的方法
4.es6继承:extends super

优点:1.既可以继承父类的属性,也可以继承父类原型对象上的方法 ​ 2.写法简单

 

    class Father {constructor(money) {this.money = money;}smoke() {console.log('抽大烟');}}class Son extends Father {constructor(name, money) {super(money);this.name = name;}}// extends来继承父类的属性和方法,必须还需要使用 super()访问父类的构造器(构造器的代码走一遍)var son = new Son("小明", 10000)console.log(son);son.smoke()// 既可以继承父类的属性,也可以继承父类原型对象上的方法

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

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

相关文章

pytorch的标签平滑介绍

什么是标签平滑(Label Smoothing)? 标签平滑(Label Smoothing)是一种正则化技术,旨在防止模型过度自信(即输出的概率分布过于“尖锐”)。在分类任务中,标准的目标标签是one-hot编码,也就是正确类别的概率为 1,其他类别的概率为 0。而标签平滑通过将正确类别的概率从…

小程序开发实战:PDF转换为图片工具开发

目录 一、开发思路 1.1 申请微信小程序 1.2 编写后端接口 1.3 后端接口部署 1.4 微信小程序前端页面开发 1.5 运行效果 1.6 小程序部署上线 今天给大家分享小程序开发系列&#xff0c;PDF转换为图片工具的开发实战&#xff0c;感兴趣的朋友可以一起来学习一下&#xff01…

基于Springboot无人驾驶车辆路径规划系统(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Hadoop:yarn的Rust API接口

今天头一次接触了yarn的Rust API接口&#xff0c;在本地搭建了集群&#xff0c;能够得到每个任务的详细信息。 (一)得到所有任务的所有信息命令&#xff1a; 默认是json格式&#xff0c;也可以指定xml的格式&#xff0c;如(curl --compressed -H "Accept: application/x…

【大模型理论篇】主流大模型的分词器选择及讨论(BPE/BBPE/WordPiece/Unigram)

1. 背景分析 分词是将输入和输出文本拆分成更小单位的过程&#xff0c;使得大模型能够处理。token可以是单词、字符、子词或符号&#xff0c;取决于模型的类型和大小。分词可以帮助模型处理不同的语言、词汇和格式&#xff0c;并降低计算和内存成本。分词还可以通过影响token的…

fmql之Linux RTC

模拟i2c&#xff0c;连接rtc芯片。 dts&#xff1a; /{ // 根节点i2c_gpio: i2c-gpio {#address-cells <1>;#size-cells <0>;compatible "i2c-gpio";// MIO56-SDA, MIO55-SCL // 引脚编号gpios <&portc 2 0&portc 1 0 >;i2c-gp…

Modbus TCP报错:Response length is only 0 bytes

问题描述&#xff1a; 使用modbus_tk库&#xff0c;通过Modbus tcp连接PLC时&#xff0c;python中的一个报错信息&#xff1a; Response length is only 0 bytes报错原因&#xff1a; 与Modbus TCP 服务端建立连接后没有断开&#xff0c;继续作为长连接使用&#xff0c;客户端…

随笔—git操作

1. 创建一个 GitHub 仓库 登录到 GitHub。点击右上角的 “” 按钮&#xff0c;然后选择 “New repository”。填写仓库名称和描述&#xff0c;选择是否公开&#xff0c;最后点击 “Create repository”。 2. 在本地初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; 在…

【Lammps】atomsk安装与环境变量设置(Linux环境)

【Lammps】atomsk安装与环境变量设置&#xff08;Linux环境&#xff09; 官网配置环境变量测试 官网 https://atomsk.univ-lille.fr/dl.php 下载的安装包如下&#xff1a; 使用Linux的解压命令进行解压&#xff1a; tar -xzvf file.tar.gz注意&#xff1a;file.tar.gz 替换…

【Vue 3】最全组件设计指南:从基础到进阶

&#x1f9d1;‍&#x1f4bc; 一名茫茫大海中沉浮的小小程序员&#x1f36c; &#x1f449; 你的一键四连 (关注 点赞收藏评论)是我更新的最大动力❤️&#xff01; &#x1f4d1; 目录 &#x1f53d; 前言1️⃣ 组件的基础概念与构建2️⃣ 组件通信的核心技术3️⃣ 组件的生命…

【文献及模型、制图分享】中国自然保护地典型治理模式成效比较——基于社区居民感知视角

采取何种治理模式能够更好地提升自然保护地治理的生态、社会和经济成效?基于制度分析与发展&#xff08;IAD&#xff09;框架&#xff0c;选择大熊猫国家公园内部及周边17个社区&#xff0c;通过问卷调查、半结构化访谈、单因素方差、逐步回归分析&#xff0c;比较统治、分治和…

CSP/信奥赛C++刷题训练:经典二分答案例题(3): 洛谷P2920:Time Management S

CSP/信奥赛C++刷题训练:经典二分答案例题(3) [USACO08NOV] Time Management S 题目描述 Ever the maturing businessman, Farmer John realizes that he must manage his time effectively. He has N jobs conveniently numbered 1…N (1 <= N <= 1,000) to accompl…

Spring Boot集成iText实现电子签章

文章目录 一 电子签章1.1 什么是电子签章1.2 签名流程1.3 技术选型 二 实战2.1 生成数字证书2.2 生成印章图片2.3 PDF 签名 一 电子签章 1.1 什么是电子签章 基于《中华人民共和国电子签名法》等相关法规和技术规范&#xff0c;具有法律效力的电子签章一定是需要使用 CA 数字…

Unbounded:一个无限生成式交互的角色生活模拟游戏

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…

Vertx实现和spring的application.yml自动配置加载

前言 在用vertx写项目的时候&#xff0c;由于需要不同的环境加载不同的配置文件&#xff0c;这里就需要和spring架构的application.yml配置文件一样&#xff0c;可以根据环境变量加载不同的配置。 代码 引入vertx相关依赖 <dependency><groupId>io.vertx</gr…

ECharts饼图-饼图自定义样式,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个饼图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供详…

猫头虎 分享:前端工具 NVM 的简介、安装、用法详解入门教程

&#x1f42f; 猫头虎 分享&#xff1a;前端工具 NVM 的简介、安装、用法详解入门教程 今天猫头虎带您深入了解 NVM&#xff01;最近&#xff0c;猫哥在项目中遇到一个前端小伙伴&#xff0c;询问如何在开发过程中高效地切换不同的 Node.js 版本。前端项目往往需要特定版本的 …

二分查找_在排序数组中查找元素的第一个和最后一个位置

1.朴素二分查找 .二分查找 二分查找思路&#xff1a; 1.left0,rightnums.size()-1&#xff08;最后一个元素下标&#xff09;&#xff0c;取中间元素下标 midleft(right-left)/2 &#xff08;防溢出&#xff09; 2.nums[mid]>target &#xff0c;说明mid右边的元素都大于ta…

Discuz 论坛开发一套传奇发布站与传奇开服表

Discuz 论坛开发一套传奇发布站与传奇开服表 随着互联网技术的飞速发展&#xff0c;网络游戏已成为人们休闲娱乐的重要方式之一。在众多网络游戏中&#xff0c;传奇系列以其独特的魅力吸引了大量忠实玩家。为了满足这些玩家的需求&#xff0c;并促进游戏信息的交流与分享&…

QtCreator通过CMake多文件编译.cpp、.qss、.h、.ui文件,达到MVC三层架构的效果

博主在构建C项目的时候&#xff0c;一般都喜欢将头文件和源文件分开为不同的文件夹&#xff0c;比如include目录下只存放.h文件和.ui文件&#xff0c;src目录下只存放.cpp和.qss文件&#xff0c;res目录下只存放图片、音频等文件&#xff0c;这时候使用CMake对项目进行分文件管…