[前端基础] JavaScript 基础篇(上)

news2024/10/7 18:20:36

JavaScript的标准是 ECMAScript 。截至 2012 年,所有浏览器都完整的支持ECMAScript 5.1,旧版本的浏览器至少支持 ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了 ECMAScript 的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为 ECMAScript 6 或者ES2015。 到现在更新到了 ECMAScript 2022(ES13)。ES6 中新特性最多,后面的版本则每次进行少量更新。

作用域

作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

JavaScript 采用词法作用域(lexical scoping),也就是静态作用域,函数的作用域在函数定义的时候就决定了。而在动态作用域中,函数的作用域是在函数调用的时候才决定的。

《JavaScript权威指南》中的例子

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope(); // => local scope

由于JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置。这里 f 函数创建在 checkscope 函数内部,所以当 f 函数找不到 scope 时,会向当前作用域,即在 checkscope 函数内部查找 scope

《JavaScript权威指南》的回答就是:

JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。

另外一个简单的例子

var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    var value = 2;
    foo();
}

bar(); // => 1

执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value = 1,所以结果会打印 1。即函数的作用域在函数定义的时候就决定了。

tips: 参考 https://juejin.cn/column/7035531575974592520

执行上下文

可执行代码
JS中分为3种:全局代码、函数代码、eval 代码。
当执行到一个函数的时候,就会创建执行上下文(execution context)
执行上下文栈
JavaScript 引擎创建了执行上下文栈(Execution context stack,ECS)来管理执行上下文我们定义执行上下文栈是一个数组:ECStack = [];

JS 开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,ECStack 才会被清空。

我们来分析下面代码:

function fun3() {
    console.log('fun3')
}

function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();

当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。

// fun1()
ECStack.push(<fun1> functionContext);

// fun2
ECStack.push(<fun2> functionContext);

// fun3
ECStack.push(<fun3> functionContext);

// fun3执行完毕
ECStack.pop();

// fun2执行完毕
ECStack.pop();

// fun1执行完毕
ECStack.pop();

对于每个执行上下文,都有三个重要属性:

  • 变量对象(Variable object,VO)
  • 作用域链(Scope chain)
  • this

变量对象
变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。变量对象中又可分为全局上下文下的变量对象函数上下文下的变量对象

  • 全局上下文下的变量对象:全局上下文中的变量对象就是全局对象。

1.在客户端 JavaScript 中,全局对象就是 Window 对象,可以通过 this 引用。

console.log(this); // window

2.全局对象是由 Object 构造函数实例化的一个对象。

console.log(this instanceof Object);

3.作为全局变量的宿主。

var a = 1;
console.log(this.a);

4.客户端 JavaScript 中,全局对象有 window 属性指向自身。

var a = 1;
console.log(window.a);

this.window.b = 2;
console.log(this.b);
  • 函数上下文下的变量对象

在函数上下文中,我们用活动对象(activation object, AO)来表示变量对象。活动对象和变量对象其实是一个东西,只是变量对象是规范上的或者说是引擎实现上的,不可在 JS 环境中访问,只有到当进入一个执行上下文中,这个执行上下文的变量对象才会被激活,所以才叫 activation object ,而只有被激活的变量对象,也就是活动对象上的各种属性才能被访问。

活动对象是在进入函数上下文时刻被创建的,它通过函数的 arguments 属性初始化。arguments 属性值是 Arguments 对象。

通过var声明的变量才被放入AO中,也会出现变量提升

执行过程

  1. 进入执行上下文

当进入执行上下文时,这时候还没有执行代码,变量对象会包括:

  • 函数的所有形参 (如果是函数上下文)
    • 由名称和对应值组成的一个变量对象的属性被创建
    • 没有实参,属性值设为 undefined
  • 函数声明
    • 由名称和对应值(函数对象(function-object))组成一个变量对象的属性被创建
    • 如果变量对象已经存在相同名称的属性,则完全替换这个属性
  • 变量声明
    • 由名称和对应值(undefined)组成一个变量对象的属性被创建;
    • 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性

举个例子:

function foo(a) {
  console.log(b) //undefined
  var b = 2;
  function c() {} // 函数
  var d = function() {}; // 变量
  var c = 1 // 不影响c

  b = 3;

}

foo(1);

在进入执行上下文后,这时候的 AO 是:

AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: undefined,
    c: reference to function c(){},
    d: undefined
}
  1. 代码执行

在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值,当代码执行完后,这时候的 AO 是:

AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: 3,
    c: reference to function c(){},
    d: reference to FunctionExpression "d"
}
  • 全局上下文的变量对象初始化是全局对象

  • 函数上下文的变量对象初始化只包括 Arguments 对象

  • 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值

  • 在代码执行阶段,会再次修改变量对象的属性值

作用域链
当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。

函数有一个内部属性 [[scope]],当函数创建的时候,就会保存所有父变量对象到其中。当函数激活时,进入函数上下文,创建 VO/AO 后,就会将活动对象添加到作用链的前端。这时候执行上下文的作用域链,我们命名为 Scope。

函数执行上下文中作用域链和变量对象的创建过程:

var scope = "global scope";
function checkscope(){
    var scope2 = 'local scope';
    return scope2;
}
checkscope();
  1. checkscope 函数被创建,保存作用域链到内部属性 [[scope]]
checkscope.[[scope]] = [
    globalContext.VO
];
  1. 执行 checkscope 函数,创建 checkscope 函数执行上下文,checkscope 函数执行上下文被压入执行上下文栈
ECStack = [
    checkscopeContext,
    globalContext
];
  1. checkscope 函数并不立刻执行,开始做准备工作,第一步:复制函数 [[scope]] 属性创建作用域链
checkscopeContext = {
    Scope: checkscope.[[scope]],
}
  1. 第二步:用 arguments 创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    }Scope: checkscope.[[scope]],
}
  1. 第三步:将活动对象压入 checkscope 作用域链顶端
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    },
    Scope: [AO, [[Scope]]]
}
  1. 准备工作做完,开始执行函数,随着函数的执行,修改 AO 的属性值
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: 'local scope'
    },
    Scope: [AO, [[Scope]]]
}
  1. 查找到 scope2 的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出
ECStack = [
    globalContext
];

在源代码中当定义(书写)一个函数的时候(并未调用),js引擎也能根据函数书写的位置,函数嵌套的位置,生成一个 [[scope]],作为该函数的属性存在(这个属性属于函数的)。

然后进入函数执行阶段,生成执行上下文,执行上下文可以宏观的看成一个对象,(包含vo,scope,this),此时,执行上下文里的scope(作用域链)和之前属于函数的那个 [[scope]] 不是同一个,执行上下文里的scope,是在之前函数的[[scope]]的基础上,又新增一个当前的AO对象构成的。

函数定义时候的[[scope]]和函数执行时候的scope,前者作为函数的属性,后者作为函数执行上下文的属性。

JS执行上下文全过程见 https://blog.csdn.net/by6671715/article/details/105241528

this 指向

var obj = {
	a: 1,
 	b: function(){console.log(this);}
 }
  1. 作为对象调用时,指向该对象 obj.b(); // 指向obj
  2. 作为函数调用, var b = obj.b; b(); // 指向全局window
  3. 作为构造函数调用 var b = new Fun(); // this指向当前实例对象
  4. 作为call与apply调用 obj.b.apply(object, []); // this指向当前的object

bind,apply,call

  • bind 创建一个新的函数,不自动执行
function fun() {
  console.log(this.name, arguments);
}
let obj = {name: 'alex'}
let b = fun.bind(obj, 'others')
b('another')
  • apply 接收一个包含多个参数的数组
function fun() {
  console.log(this.name, arguments);
}
let obj = {name: 'alex'}
fun.apply(obj, ['other'])
  • call 接收一个参数列表
function fun() {
  console.log(this.name, arguments)
}
let obj = { name: 'alex' }
fun.call(obj, 'other')

闭包

MDN 闭包

闭包(closure)是一个函数以及其捆绑的周边环境状态,让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。

经典例子

<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>
function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp(); // 将全部提示 'Your age (you must be over 16)'

赋值给 onfocus 的是闭包,这些闭包是由他们的函数定义和在 setupHelp 作用域中捕获的环境所组成的。这三个闭包在循环中被创建,但他们共享了同一个词法作用域,在这个作用域中存在一个变量 item。这是因为变量 item 使用 var 进行声明,由于变量提升,所以具有函数作用域。当 onfocus 的回调执行时,item.help 的值被决定。由于循环在事件触发之前早已执行完毕,变量对象 item(被三个闭包所共享)已经指向了 helpText 的最后一项。

解决办法1:

// 嵌套闭包
function makeHelpCallback(help) {
  return function() {
    showHelp(help);
  };
}
document.getElementById(item.id).onfocus = makeHelpCallback(item.help)

解决办法2:

// 立即执行函数(匿名闭包)
(function() {
	var item = helpText[i];
	document.getElementById(item.id).onfocus = function() {
		showHelp(item.help);
	}
})(); 

解决办法3:

// 使用 let 避免 var 变量提升
for (let i = 0; i < helpText.length; i++) {
	//...
}

原型

__proto__

每个JavaScript对象(除了 null )都具有的一个属性,这个属性会指向该对象的原型。

function Person() {
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person = new Person('Alex', 16);
// Person 类型实例的原型,默认也是一个空对象
console.log(person.__proto__); // => Person {}
//es6 新方法
console.log({}.__proto__ === Object.getPrototypeOf({})); // true

可以直接修改对象的原型,不过被设置的值的类型只能是对象或者 null,其它类型不起作用:

const obj = { name: 'Alex' };
console.log(obj.__proto__); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}

obj.__proto__ = 666;
// 非对象和 null 不生效
console.log(obj.__proto__ === Object.prototype); // true

obj.__proto__ = null;
// 设置为 null 返回 undefined
console.log(obj.__proto__=== Object.prototype); // false

// 设置原型为对象
obj.__proto__ = { constructor: 'Function Student' };
console.log(obj.__proto__); // { constructor: 'Function Student' }

如果被设置的值是不可扩展的,将抛出 TypeError:

const frozenObj = Object.freeze({});
// Object.isExtensible(obj) 可以判断 obj 是不是可扩展的
console.log(Object.isExtensible(frozenObj)); // => false
frozenObj.__proto__ = null; // => TypeError: #<Object> is not extensible

注:原型上的属性都是不可枚举的:Object.keys(obj)// [ ]

其实 __proto__ 是个访问器属性(getter 和 setter 都有),通过 __proto__ 访问器我们可以访问对象的 [[Prototype]], 也就是原型。

Object.prototype = {
  get __proto__() {
    return this['[[prototype]]'];
  },
  set __proto__(newPrototype) {
    if (!Object.isExtensible(newPrototype)) throw new TypeError(`${newPrototype} is not extensible`);

    if (newPrototype === null) {
      this['[[prototype]]'] = undefined;
      return;
    }

    const isObject = typeof newPrototype === 'object' || typeof newPrototype === 'function';

    if (isObject) {
      this['[[prototype]]'] = newPrototype;
    }
  }
};

prototype

function Person() {
}
Person.prototype.name = 'Alex';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Alex
console.log(person2.name) // Alex

这里,Person 就是一个构造函数,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是这个例子中的 person1 和 person2 的原型。
可以将原型理解为: 每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。

每个函数都有一个 prototype属性,默是一个空的纯对象,所有由构造器构造的实例的原型都是指向它 ,比如:

// 实例的原型即 person1.__proto__
console.log(person1.__proto__ === Person.prototype); // => true
console.log(person2.__proto__ === Person.prototype); // => true

constructor
在 JavaScript 中,函数都可以用作构造器。构造器我们也可以称之为类,我们可以通过 new 构造器来构造一个实例。如上面的person1,person2。

每个原型都有一个 constructor 属性指向关联的构造函数。

function Person() {
}
console.log(Person === Person.prototype.constructor); // true

__proto__ ,prototype,constructor,Person函数,实例 person 和原型对象 [[prototype]] 之间的关系:

__proto__ 存在于所有的对象上,prototype 存在于所有的函数上,他俩的关系就是:函数的 prototype 是所有使用 new 这个函数构造的实例的 __proto__。函数也是对象,所以函数同时有 __proto__ 和prototype。

实例与原型

当在一个对象 obj 上访问某个属性时,如果不存在于 obj,那么便会去对象的原型也就是 obj.__proto__ 上去找这个属性。如果有则返回这个属性,没有则去对象 obj 的原型的原型也就是 obj.__proto__.__proto__去找,重复以上步骤。一直到访问纯对象的原型的原型{}.__proto__.__proto__,也就是 null,直接返回 undefined。

function Person() {
}

Person.prototype.name = 'Kevin';

var person = new Person();

person.name = 'Daisy';
console.log(person.name) // Daisy

delete person.name;
console.log(person.name) // Kevin

原型链
由上可知Object.prototype 的原型为null,即Object.prototype.__proto__ 的值为 null ,也可以说 Object.prototype 没有原型。所以查找属性的时候查到 Object.prototype 就可以停止查找了。

各个原型之间构成的链,我们称之为原型链。

函数(构造器) Person 的原型链:

原型的用途
在使用构造器定义一个类型的时候,一般会将类的方法定义在原型上

function Cat(workingYears) {
  this.category = category;
}

// 不能使用箭头函数,箭头函数的 this 在声明的时候就根据上下文确定了
Cat.prototype.voice = function() {
  console.log(`${this.category} miaomiao叫`);
};

const cat = new Cat('大橘');
cat.voice(); // 大橘 miaomiao叫

通过这种方式,所有的实例都可以访问到这个方法,并且这个方法只需要占用一份内存,节省内存,this 的指向还能正确指向类的实例。不过这种方式定义的方法都是不可枚举的,毕竟不是自身的属性:

const obj = {
  func() {}
};

console.log(Object.keys(obj)); // => [ 'func' ]

function Func() {}
Func.prototype.func = function() {};
// 空数组,说明 func 不可枚举
console.log(Object.keys(new Func())); // => []

类的创建/继承

ES6 class
ES6 class 就是构造器的语法糖。ES6 的 class 就是构造器,class 上的方法定义在构造器的 prototype 上。

class Person {
	constructor(name) {
		// 构造函数 
		this.name = name
	}
}

// extends 继承
class Male extends Person {}

let male = new Male('Alex')

console.log(male.__proto__.__proto__ === Person.prototype) // true
console.log(Male.__proto__ === Person) // true

原型继承

对于类 A 和类 B,如果满足 A.prototype.__proto__ === B.prototype,那么 A 原型继承 B

实现方法1

function A() {}
function B() {}

A.prototype = new B();

console.log(A.prototype.__proto__ === B.prototype); // true

实现方法2 (避免 B 的实例属性污染 A 的原型)

function A(p) {
  this.p = p;
}

function B() {}

// 空函数
function Empty() {}

Empty.prototype = B.prototype;
A.prototype = new Empty();
// 修正 constructor 指向
A.prototype.constructor = A;

// 满足原型继承的定义
console.log(A.prototype.__proto__ === B.prototype); // => true

const a = new A('p');
console.log(a instanceof A); // => true

const b = new B();
console.log(b instanceof B); // => true

// a 也是 B 的实例
console.log(a instanceof B); // => true
console.log(a.__proto__.__proto__ === B.prototype); // => true

实现方法3 (利用 Object.create):

function _inheritsLoose(subClass, superClass) {
  // Object.create(prototype) 返回一个以 prototype 为原型的对象
  subClass.prototype = Object.create(superClass.prototype);
  subClass.prototype.constructor = subClass;
  subClass.__proto__ = superClass;
}

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

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

相关文章

steam搬砖项目全面讲解,月入8000+

哈喽大家好&#xff0c;我是阿阳 今天给大家分享CSGO搬砖项目&#xff0c;这个是最为稳定利润可观的项目&#xff0c;一个月净赚3万 阿阳网络创始人&#xff0c;8年互联网项目实战经验&#xff0c;个人ip打造【玩赚steam&#xff0c;3年买2套房】国外steam游戏搬砖&#xff08…

[附源码]java毕业设计文档管理系统

项目运行 环境配置&#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…

Java中Callable和Future

Java中为什么需要Callable 在java中有两种创建线程的方法&#xff1a; 一种是继承Thread类&#xff0c;重写run方法&#xff1a; public class TestMain {public static void main(String[] args) {MyThread t1 new MyThread();t1.start();} } class MyThread extends Thre…

值得学习的Linux内核锁(一)

在linux系统当中存在很多独占性的资源&#xff0c;他在同一个时间只能被一个进程使用。常见的有打印机、内存或者系统内部表现等资源。如果打印机同时被两个进程使用&#xff0c;打印结果就会混乱输出结果&#xff1b;如果一个内存资源被多个进程同时修改&#xff0c;进程实际的…

【Hack The Box】linux练习-- Networked

HTB 学习笔记 【Hack The Box】linux练习-- Networked &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月17日&#x1f334; &#x…

Java多线程从基本概念到精通大神,大佬给我们铺平学习之路

Java 提供了多线程编程的内置支持&#xff0c;让我们可以轻松开发多线程应用。 Java 中我们最为熟悉的线程就是 main 线程——主线程。 一个进程可以并发多个线程&#xff0c;每条线程并行执行不同的任务。线程是进程的基本单位&#xff0c;是一个单一顺序的控制流&#xff0c;…

常见的限流算法与实现

限流的实现 常见的限流算法&#xff1a; 限流是对某一时间窗口内的请求数进行限制&#xff0c;保持系统的可用性和稳定性&#xff0c;防止因流量暴增而导致的系统运行缓慢或宕机。 常见的限流算法有三种&#xff1a; 计数器限流(固定窗口) 原理&#xff1a; 时间线划分为多…

Dubbo3.0入门-Java版

Dubbo 简介 ​ Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo 提供的丰富服…

【软件测试】测试人终将迎来末路?测试人的我35岁就坐等失业?

目录&#xff1a;导读一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;一句话萦绕在耳畔测试乃至测开…

02 LaTex之小tips

1.运行 2.头&#xff0b;尾 \documentclass[11pt]{article}\usepackage{algorithm, algpseudocode} \usepackage{amsmath,amssymb,amsthm} \usepackage{mathrsfs}% huaxie zimu \textwidth 16cm\textheight 22cm\oddsidemargin0cm\evensidemargin\oddsidemargin\usepackage{un…

Java#17(static)

目录 一.静态关键字static 1.静态变量(被static修饰的成员变量) 2.静态方法(被static修饰的成员方法) 扩展:工具类的简单使用 三.static关键字的注意事项 一.静态关键字static 1.静态变量(被static修饰的成员变量) 特点: (1)被该类的所有对象共享 (2)不属于对象,属于类 (3)…

版权交易平台app开发,构建版权元宇宙生态

近年来在国家的大力宣传推广下&#xff0c;人们在版权方面的保护意识逐步提高&#xff0c;大力发展版权交易市场&#xff0c;不仅是响应国家号召的体现&#xff0c;更是保护公民合法权益的重要举措。版权交易平台app的开发为创业者提供了一个全新投资方向&#xff0c;同时app还…

带你认识工厂类设计模式——简单工厂工厂方法抽象工厂简单抽象工厂反射简单抽象工厂

工厂类设计模式简单工厂模式简单工厂模式类图简单工厂实现代码实现小结工厂方法模式工厂方法模式类图工厂方法模式代码实现小结抽象工厂模式抽象工厂模式类图抽象工厂模式代码实现小结&#xff1a;用简单工厂改进抽象工厂模式简单抽象工厂模式类图简单抽象工厂模式代码实现小结…

高项 人力资源管理论文

4个过程&#xff1a; 人力资源管理简单可以归纳为以下四点&#xff1a;明确需要的人&#xff08;&#xff08;制定人力资源管理计划&#xff09;&#xff0c;找到合适的人&#xff08;组建项目团队&#xff09;&#xff0c;用好身边的人&#xff08;建设项目团队&#xff09;&…

宝塔面板一键部署芸众商城智慧商业系统 打造多终端直播分销商城

芸众商城社交电商系统前端基于vue开发&#xff0c;后端基于laravel开发&#xff0c;免费版本全开源&#xff0c;支持商用&#xff0c;可同时支持多端口部署运行&#xff1b;本教程将使用宝塔面板一键部署的方式搭建芸众商城系统&#xff0c;使用宝塔面板搭建&#xff0c;大大提…

ShardingSphere实现数据库读写分离,主从库分离,docker详细教程

一.什么是 ShardingSphere 引用官方的话&#xff1a; Apache ShardingSphere 是一款分布式的数据库生态系统&#xff0c; 可以将任意数据库转换为分布式数据库&#xff0c;并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。 Apache ShardingSphere 设计哲学为 Dat…

计算机毕业设计ssm+vue基本微信小程序的购物商城系统

项目介绍 随着互联网的趋势的到来,各行各业都在考虑利用互联网将自己的信息推广出去,最好方式就是建立自己的平台信息,并对其进行管理,随着现在智能手机的普及,人们对于智能手机里面的应用购物平台小程序也在不断的使用,本文首先分析了购物平台小程序应用程序的需求,从系统开发…

希望所有计算机专业学生都去这些网站刷题

LeetCode 力扣&#xff0c;强推&#xff01;力扣虐我千百遍&#xff0c;我待力扣如初恋&#xff01; 从现在开始&#xff0c;每天一道力扣算法题&#xff0c;坚持几个月的时间&#xff0c;你会感谢我的&#xff08;傲娇脸&#xff09; 我刚开始刷算法题的时候&#xff0c;就选…

[vue] nodejs安装教程

介绍&#xff1a;nodejs 是一个开源的跨平台的JavaScript运行时环境&#xff0c;因此在运行前端项目时是需要安装配置相应的环境变量。 一、下载nodejs 二、安装nodejs 三、配置nodejs的环境变量 四、验证配置的nodejs 一、下载nodejs nodejs下载官网地址&#xff1a;下载 …

【C++基础】this指针

this指针 this指针作用&#xff1a; c的数据和操作也是分开存储&#xff0c;并且每一个非内联成员函数只会诞生一份函数实例&#xff0c;也就是说多个同类型的对象会共用同一块代码。所以&#xff0c;用this指针表明哪个对象调用自己。 定义&#xff1a; this指针指向被调用的…