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

Js高级API

Decorator装饰器

针对属性 / 方法的装饰器

// decorator 外部可以包装一个函数,函数可以带参数function Decorator (type) {/*** 这里是真正的decorator* @description: 装饰的对象的描述对象* @target:装饰的属性所述类的原型,不是实例后的类。如果装饰的是Animal的某个属性,这个target就是Animal.prototype* @name 装饰的属性的key*/return function (target, name, desciptor) {// 因为babel的缘故 通过value并不能获取值,以此可以获取实例化的时候此属性的默认值let v = desciptor.initializer && desciptor.initializer.call(this)// 返回一个新的描述对象,或者直接修改desciptor也可以return {enumerable: true, //可以遍历configurable: true, //可以删除get: function () {return v},set: function (c) {v = c}}}}// 上面的不能和业界商用的Decorator混用function Check (type) {return function (target, name, desciptor) {let v = desciptor.initializer && desciptor.initializer.call(this)// 将属性名字以及需要的类型的对应关系记录到类的原型上if (!target.constructor._checkers_) {// 将这个隐藏属性定义成no enumerable,遍历的时候是取不到的Object.defineProperty(target.constructor, '_checkers_', {value: {},enumerable: false,writable: true,configurable: true})}target.constructor._checkers_[name] = {type: type}return desciptor}}// 装饰函数的第一个参数 target 是包装属性所属的类的原型(prototype)// 也就是把对应关系挂载到了开发定义的子类上。

vue中使用Decorator

  • ts开发一定对vue-property-decorator不会感到陌生,这个插件提供了许多装饰器

  • 在methods里面的方法上面使用装饰器,这时候装饰器的target对应的是methods。

  • 可以在生命周期钩子函数上面使用装饰器,这时候target对应的是整个组件对象。

  import {log,confirmation} from "./test"methods: {@log()name() {console.log("获取数据");},@confirmation('此操作将永久删除文件,是否继续?')deleteFile(data){//删除文件操作}},mounted () {this.name()}

test.js

 import {MessageBox}from "element-ui"
export function confirmation(message){return function(target,name,descriptor){let oldValue = descriptor.valuedescriptor.value = function(...args){MessageBox.confirm(message,'提示').then(oldValue.bind(this,...args)).catch(()=>{})}return descriptor}
}
export function log(){/*** @description: * @param {*} target  对应methods* @param {*} name 对应属性方法的名称* @param {*} descriptor 对应属性方法的修饰符* @return {*}*/      return function(target,name,descriptor){console.log(target,name,descriptor);// 获取实例化的时候此属性的默认值const fn = descriptor.value/* 重写 */descriptor.value = function(...rest){console.log(`调用${name}方法打印的`);fn.call(this,...rest)}}}

Iterator 迭代器

  • 目的是为不同的数据结构提供统一的数据访问机制 主要为for of 服务的 (当for of执行的时候,循环过程中会自动调用这个对象上的迭代器方法,依次执行迭代器对象的next方法,并把next返回结果赋值给for of的变量,从而得到具体的值

  • 迭代器对象,返回此对象的方法叫做迭代器方法 此对象有一个next方法 每次调用next方法都会返回一个结果值

  • 这个结果值是一个object 包含两个属性value和done

  • value表示具体的返回值 done是布尔类型的,表示集合是否遍历完成或者后续还有可用数据,没有可用返回true, 否则返回false

  • 内部会维护一个指针 用来指向当前集合的位置 每调用一次next方法 指针都会向后移动一个位置(可以想象成数组的索引)

    代码实现

  getInterator(list){var i = 0;return {next:function(){var done = (i>=list.length);var value = !done ? list[i++]:undefinedreturn {done:done,value:value}}}}var it = this.getInterator(['a','b','c'])console.log(it.next());// {done: false, value: 'a'}console.log(it.next());//{done: false, value: 'b'}console.log(it.next());//{done: false, value: 'c'}console.log(it.next());//{done: true, value: undefined}
可迭代对象
  • Symbol.Iterator是一个表达式 返回Symbol的Iterator属性, 这是一个预定好的类型为Symbol的特殊值

  • ES6规定,只要在对象上部署了Iterator接口,具体实现为给对象添加Symbol.Iterator属性,此属性指向一个迭代器方法,这个迭代器会返回一个迭代器对象。

  • 而部署了这个属性,并且实现迭代器方法 返回的对象就是迭代器对象,此时这个对象就是可迭代的 可以被for for遍历

    实现一个可迭代对象

     getIterator(){let iteratorObj = {items:[100,200,300],[Symbol.iterator]: function(){var self = thisvar i =0return {next:function(){var done = (i>=self.items.length)var value = !done?self.items[i++]:undefinedreturn {done:done,value:value}}}}}for(var item of iteratorObj){console.log(item); //100 200 300}}//上面的对象就是可迭代对象,可以被for of遍历this.getIterator()
    
    for of 中断

    如果for of 循环提前退出,则会自动调用return方法,需要注意的是return 方法必须有返回值,且返回值必须是一个object

     var arr = [100, 200, 300]arr[Symbol.iterator] = function () {var self = thisvar i = 0return {next: function () {var done = i >= self.lengthvar value = !done ? self[i++] : undefinedreturn {done: done,value: value}},return (){console.log('提前退出');return { //必须返回一个对象done:true}}}}for (var o of arr) {if(o == 200){break;}console.log(o) // 100   提前退出}
    

    除了for of 会调用对象的Iterator, 结构赋值也会

        var str = '123'let [a,b]=strconsole.log(a,b); // 1 2let map = new Map()map.set('q','1')map.set('a','2')map.set('b','3')let [c,d] = mapconsole.log(c,d); //['q', '1'] ['a', '2']
    

    因为普通对象不是可迭代对象。

    自定义的可迭代对象进行解构赋值

     var interatorObj = {items: ['橙', '红', '白'],[Symbol.iterator]: function () {let i = 0let self = thisreturn {next: function () {let done = i >= self.items.lengthlet value = !done ? self.items[i++] : undefinedreturn {done: done,value: value}}}}}let [a,b] = interatorObjconsole.log(a,b); //橙 红
    

    解构赋值的变量的值就是迭代器对象next方法的返回值 且是按顺序返回

    扩展运算符

    // 扩展运算符的执行(…)也会默认调用它的Symbol.iterator方法,可以将当前迭代对象转换为数组

    */\* 字符串 \*/*var str = "1234"console.log([...str]);*//【1,2,3,4】转换成数组**/\* map对象\*/*var map = new Map([[1,2],[3,4]])[...map]*//[[1,2],[3,4]]**/\* set对象 \*/*var set = new Set([1,2,3])[...set] *//[1,2,3]*
    

    使用普通对象是不可以转换为数组的

    var obj = {name:'zhang'}[...obj] *//报错*
    
作为数据源

作为一些数据的数据源 比如某些参数是数组的API方法,都会默认的调用自身的迭代器

例如 map set Array.from等

为了证明,先把一个数组的默认迭代器给覆盖掉

var arr= [100,200,300]arr[Symbol.iterator]=function(){var self = thisvar i = 0;return {next:function(){var done = (i>=self.length)var value = !done?self[i++]:undefinedreturn {done:done,value:value + '前端'}}}}

用for of

 for(var o of arr){console.log(o);//100前端 200前端 300前端}

生成set对象

  var set = new Set(arr)set*//Set(3) {'100前端', '200前端', '300前端'}*

调用Array.from方法

  Array.from(arr) *//['100前端', '200前端', '300前端']*
*yield**关键字

​ *yield**后面跟的是一个可遍历的结构,执行时也会调用迭代器函数

 let foo = function*(){​        *yield* 1;​        *yield** [1,2,3];​        *yield* 5;​      }
判断对象是否可迭代

既然可迭代对象的规则必须在对象上部署Symbol.iterator属性,那么就可以依次来判断是否为可迭代对象,然后就知道是否能使用for of 取值了

  function isIterable(*object*){​        *return* typeof *object*[Symbol.iterator] === 'function'​      }​      console.log(isIterable('asdd'));*//true*​      console.log(isIterable([1,2,3]));*//true*​      console.log(isIterable(new Map()));*//true*​      console.log(isIterable(new Set()));*//true*​      console.log(isIterable(new WeakMap()));*//false*​      console.log(isIterable(new WeakSet()));*//false
Generate生成器*
 let obj = {​      *[Symbol.iterator]("Symbol.iterator"){​        *yield* 'hello';​        *yield* 'world';​      }​    }​    *for*(let x of obj){​      console.log(x);​    } *//hello world

Generator

Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同

Generator函数将javascript异步编程带入了一个全新的阶段

声明

与函数声明类似,不同的是function关键字与函数名之间有一个星号,以及函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是产出)

 function* foo(){yield 'result1'yield 'result2'yield 'result3'}const gen = foo()console.log(gen.next().value);console.log(gen.next().value);console.log(gen.next().value);

vue中使用

 textMy () {const gen = this.foo()console.log(gen.next().value);console.log(gen.next().value);console.log(gen.next().value);},* foo(){yield 'result1'yield 'result2'yield 'result3'}

​ 执行Generator会返回一个对象,而不是像普通函数返回return 后面的值

​ 调用指针next方法,会从函数的头部或上一次停下来的位置开始执行,直到遇到下一个yield表达式或者return语句暂停,也就是执行yeild这一行

​ value就是执行yield后面的值 done表示函数是否执行完毕

console.log(g.next()); *//{value: 7, done: false}*​      console.log(g1.next()); *//{value: 2, done: false}*​      console.log(g.next());*//{value: undefined, done: true}

​ 因为最后一行 return y 被执行完成 所以done为true

​ 调用Generator函数后,该函数并不执行,返回的也不是函数运行结果 而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object).必须调用遍历器对象的next方法

​ 使得指针移向下一个状态

      function* fetch(){​        *yield* ajax('aaa')​        *yield* ajax('bbb')​        *yield* ajax('ccc')​      }​      let gen = fetch()​      let res1 = gen.next() *//{value:'aaa',done:false}*​      let res2 = gen.next() *//{value:'bbb',done:false}*​      let res3 = gen.next() *//{value:'ccc',done:false}*​      let res4 = gen.next() *//{value:undefined,done:true} //done为true表示执行结果

由于Generator函数返回的是遍历器对象 只有调用next方法才会遍历下一个内部状态 所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志

​ 遍历器对象的next方法运行逻辑:

​ 1 遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的表达式的值,作为返回对象的value属性值

​ 2. 如果下次调用next方法时,再继续往下执行,直到遇到下一个yield表达式

​ 3 如果没有再遇到新的yiled表达式 就一直运行到函数结束

​ 4 如果该函数没有return 语句 则返回对象的value属性值就是underfined

​ yiled表达式本身没有返回值 或者说总返回underfined next 方法可以带一个参数,该参数就会被当做上一个yield表达式的返回值

​ 一个函数可以有多个yield,但是只能有一个return

Proxy

​ - Proxy用于创建对象的代理,用于监听对象的相关操作。代理对象可以监听我们对原对象的操作

​ - 在实例化Proxy对象时,第二个参数传入的是捕获器集合,我们在其对象内定义一个get捕获器,用于监听获取对象值的操作

​ - objProxy 对象的拦截器中set捕获器,用于监听对象的某个属性被设置时触发

// 定义一个普通的对象const obj = {name:'_isLand'}// 代理obj这个对象  并传入get捕获器const objProxy = new Proxy(obj,{// get捕获器get:function(target,key){console.log(`触发对象捕获${key}`);return target[key]},set:function(target,key,val){console.log(`捕获到对象设置${key},新值为${val}`);return target[key] = val}})objProxy.name = 'liming'// 通过代理对象操作obj对象console.log(objProxy.name);//触发对象捕获name  _isLand// 捕获到对象获取name属性值的操作

如果不想这个属性被设定成这个值,你可以抛出异常告诉开发者,这个值不能设定

 set:function(target,key,val){if(key==='age' && typeof val ==='number'){return target[key] = val}else{throw new TypeError('该属性的值必须是number类型')}}

监听对象是否调用了getPrototypeof操作,使用getPrototypeOf捕获器

 getPrototypeOf:function(){console.log('监听到对象的protptypeOf操作');}

Proxy一共有十三个捕获器,用于我们对 对象或者函数的方法调用的监听

请添加图片描述

this指向的问题

​ Proxy对象可以对我们的目标对象进行访问,但没有做任何拦截时,也不能保证与目标行为一致,因为目标对象 内部的this会自动改变为Proxy代理对象

      let obj = {name:'lili',foo:function(){return this === objProxy}}let objProxy = new Proxy(obj,{})console.log(obj.foo()); //falseconsole.log(objProxy.foo());  //true
对象监听

​ 在vue2中的watchApi是使用的Es5的Object.defineProperty(对象属性描述符)对对象监听,将一个对象进行遍历,

​ 并设定setter。getter方法进行监听和拦截

const obj = {name: 'liki',age: 12}Object.keys(obj).forEach(key => {let val = obj[key]Object.defineProperty(obj, key, {get: function () {console.log('触发get')return val},set: function (newVal) {console.log('触发set')val = newVal}})})obj.age = 100console.log(obj.name);
  • Object.defineProperty的设计初衷并不是为了去拦截拦截一个对象中的属性,且他也实现不了更加丰富的操作,例如删除、添加属性等操作

​ - 所以在Es6中新增了Proxy,对象,用于监听Object,Function的操作。

​ - 在Vue3框架中的响应式原理也是用到了Proxy对象进行对属性的监听操作

proxy是一个代理对象 他可以代理我们对原目标的操作。相比Object.defineProperty方法 Proxy监听的事件更加方便

Reflect隐射对象

Reflect是一个对象,翻译过来就是反射的意思,它提供了很多操作Javascript对象的方法,是为弥补Object中对象的一些缺陷。且所有的属性和方法都是静态的

最初,js的一些内部方法都是放在Object这个对象上的,比如getPrototye,defineProperty等API,

in、delete操作符都放在了Object对象上。但是Object作为一个构造函数,这些方法都放在Object上并不合适,

所以ES6之后的内部新方法都在Reflect对象中。Refelect不是构造函数

使用Reflect对象操作Object对象

Reflect对象让我们操作Object对象不再是通过点语法 而是变成了函数行为

所以 获取对象属性可以使用Reflect.get方法,将对象的属性赋值使用Reflect.set方法

    const obj = {name:'lili',age:12}/* 获取对象的属性值 */console.log(obj.name);console.log(Reflect.get(obj,'name'));//  对对象的属性赋值obj.name = 'lala'Reflect.set(obj,'name','lala')console.log(Reflect.get(obj,'name'));// 判断一个对象中是否有该属性console.log('name' in obj);console.log(Reflect.has(obj,'name'));

Reflect中的方法

请添加图片描述

在返回值方面Reflect对象中的方法设计的更加合理 比如defineProperty方法,如果没有将属性设置

成功,在Reflect中会返回boolean值,而Object对象中如果没有定义成功则会抛出TypeError

Reflect搭配Proxy

​ Reflect对象中的方法和Proxy对象中的方法对应的,Proxy对象中的方法也能在Reflect对象中调用

​ 通常我们将Reflect对象搭配Proxy一起使用

在下面Proxy对象中get,set捕获器多了一个recerive参数 这是这两个捕获器特有的 代表的是当前的代理对象

​ 当Proxy和Reflect搭配使用时 Proxy对象会拦截对应的操作 后者完成对应的操作,如果传入receiver,那么Reflect.get属性

​ 会触发Proxy.definProperty捕获器。如果没有传入receive参数 则不会触发defineProperty捕获器

     let obj = {name:'lili'}const objProxy = new Proxy(obj,{get:function(target,key,receiver){return Reflect.get(target,key,receiver)},set:function(target,key,val,receiver){return Reflect.set(target,key,val,receiver)},defineProperty:function(target,key,attr){console.log('defineProperty',target,key,attr); //defineProperty {name: 'lili'} name {value: 'ppp'}return Reflect.defineProperty(target,key,attr)}})objProxy.name = 'ppp'console.log(objProxy.name);//传入在我们获取代理对象中的name属性时,当Reflect有receive

总结

​ - Reflect 对象中集合了javascript内部方法

​ - 操作Object对象的方式变成了函数行为

​ - Reflect 对象中的方法返回结果更加合理

ES6中的class

​ 在ES6之前,js语法是不支持类的,导致面向对象编程无法直接使用,而是通过function来实现模拟类,随着js的更新,ES6中出现了Class,

​ 用于定义类

 class Animal {}const Animal = class {}
类的构造函数

每一个类都可以有一个自己的构造函数,这个名称是固定的construtor,当我们通过new 调用一个类时,这个类就会调用自己的constructor方法(构造函数)

​ - 它用于创建对象时给类传递一些参数

​ - 每一个类只能有一个构造函数

​ - 通过 new 调用一个类时 会调用构造函数 执行如下操作

​ 1 在内存中开辟一块新的空间用于创建新的对象

​ 2 这个对象内部的_proto_属性会被赋值为该类的prototype属性

​ 3 构造函数内部的this,指向创建出来的新对象

​ 4 执行构造函数内部的代码

​ 5 如果函数没有返回值 则返回this

 class Animal {constructor(name){this.name = name}}var a = new Animal("ABC")console.log(a); //Animal {name: 'ABC'}

class 中定义的constructor,这个就是构造方法

而this代表的是实例对象

这个class 可以看作是构造函数的另一种写法 因为它和它的构造函数的相等的,即是 类本身指向构造函数

console.log(Animal === Animal.prototype.constructor); *//true*

所以其实类上的所有方法都会放到prototype属性上

类中的属性

实例属性

​ 实例的属性必须定义在类的方法中

class Animal {constructor(name,height,weight){this.name = namethis.height = heightthis.weight = weight}}

静态属性

​ 当我们把一个属性赋值给类本身,而不是赋值给它的prototype,这样子的属性被称之为静态属性(static)

​ 静态属性直接通过类来访问 无需在实例中访问

class Foo{static name = "liLI"}console.log(Foo.name);

私有属性

​ 私有属性只能在类中读取,写入,不能通过外部引用私有字段

   class Person{#age;constructor(age,name){this.#age = agethis.name = name}}var a = new Person(17,'lili')console.log(a); //Person {name: 'lili'}console.log(a.name);//liliconsole.log(a.age);//undefinedconsole.log(a.#age);// Private field '#age' must be declared in an enclosing class

console.log(Object.getOwnPropertyDescriptors(a));

通过getOwnPropertyDescriptors获取属性同样获取不到

 {name: {value: '_island',writable: true,enumerable: true,configurable: true}}

在ES6之前,我们定义类中的方法是类中的原型上定义的 防止类中的方法重复在多个对象中

 function Animal{}​      Animal.prototype.eating = function(){​        console.log(this.name + 'eating');​      }

在Es6中定义类中的方法更简洁 直接在类中定义即可 这样的写法优雅可读性也强

  class Animal{eating(){​         console.log(this.name + 'eating');​       }​     }
静态方法

静态方法是与静态属性是一样的 在方法前面加上stati关键字声明,之后调用这个方法时不需要通过类的实例来调用,可以直接通过类名来调用它

 class Animal{​        static creatName(*name*){​          *return* *name*​        }​      }​      var a2 = Animal.creatName('lll')​      console.log(a2); *//lll
私有方法

在面向对象中 私有方法是一个常见需求 ES6中没有提供,可以通过某个方法实现它

   class Foo{​        _getBoodType(){​          *return* '0'​        }​      }

需要注意的是,通过下划线开头通常我们会局限它是一个私有方法 但是在类的外部还是可以正常调用到这个方法的

类的继承

extends关键字用于扩展子类,创建一个类作为另一个类的子类

​ 它会将父类中的属性和方法一起继承到子类的,减少子类中重复的业务代码

​ 这比之前在ES5中修改原型链实现继承的方法可读性要强的多,而且写法更简洁

       extends的使用​      class Animal{}​      dog继承Animal类​      class dog extends Animal{}

继承类的属性和方法

  • 定义一个dog类 通过extends关键字继承Animal类的属性和方法
  • 在子类的construtor方法中 使用super关键字,在子类中它上市必须存在的 否则新建实例会抛出异常。
  • 这是因为子类的this对象是继承父类的this对象 如果不调用super方法 子类就得不到this对象

class Animal {​        constructor (*name*) {​          this.name = *name*​        }​        eating () {​          console.log(this.name + 'eating')​        }​      }​      class dog extends Animal{​        constructor(*name*,*legs*){​          super(*name*)​          this.legs = *legs*​        }​        speaking(){​          console.log(this.name + "speaking");​        }​      }​      var wang = new dog('tom',4)​      wang.speaking()​      wang.eating()​      console.log(wang.name);
Super

super关键字用于访问调用一个对象的父对象上的函数

​ super指的是超级,顶级,父类的意思

​ 在子类的构造函数中使用this或者返回默认对象之前,必须先使用super调用父类的构造函数

​ 子类的construtor方法先调用了super方法,它代表了父类的构造函数,也就是我们把参数传递进去之后,其实它调用了父类的构造函数

 class Animal{​        constructor(*name*)​      }​      class dog{​        constructor(*name*,*type*,*weight*){}​        super(*name*)​        this.type = type​        this.weight = weight​      }

使用super调用父类的方法

				 class Animal{​        constructor(*name*){​          this.name = name​        }​        eating(){​          console.log(this.name + 'eating');​        }​      }​      *// dog继承Animal类*​      class dog extends Animal{​        constructor(*name*,*lengs*){​          super(*name*)​          this.lengs = *lengs*​        }​        speaking(){super.eating()​          console.log(this.name + 'speaking');​        }​      }​        var a = new dog('旺财',4)​        a.speaking() *//旺财eating  旺财speaking
Getter和Setter

在类内部可以使用get和set关键字,对应某个属性设置存值和取值函数,拦截属性的存取行为

 class Animal{​        constructor(){​          this._age = 3​        }​        get age(){​          console.log('get');​          *return* this._age​        }​        set age(*val*){​          console.log('set');​          this._age = val​        }​      }​      var a = new Animal()​      console.log(a.age);​      a.age = 4​      console.log(a.age);
关于class扩展

严格模式

在类和模块的内部 默认是严格模式 所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用

name属性

Es6中的类只是Es5构造函数的一层包装,所以函数的许多属性都被class继承了,包括name属性

 class Animal{}console.log(Animal.name);

变量提升

class不存在变量提升,这与Es5中实现类是不同的, function关键字会存在变量提升

   new Foo() * ReferenceError*class Foo{}

在Es6之后,在定义类以及它内部的属性方法,还有继承操作的语法变得很简洁易懂

class 是一个语法糖 其内部还是通过Es5中的语法实现的。且有些浏览器不支持class语法 我们可以通过babel来进行转换

相关文章:

Js高级API

Decorator装饰器 针对属性 / 方法的装饰器 // decorator 外部可以包装一个函数,函数可以带参数function Decorator (type) {/*** 这里是真正的decorator* description: 装饰的对象的描述对象* target:装饰的属性所述类的原型,不是实例后的类。如果装饰…...

团队:在人身上,你到底愿意花多大精力?

你好,我是叶芊。 今天我们讨论怎么带团队这个话题,哎先别急着走,你可能跟很多人一样,觉得带团队离我还太远,或者觉得我才不要做管理,我要一路技术走到底,但是你知道吗?带团队做事&am…...

Linux-Poolkit提权

Linux-Poolkit提权 漏洞复现- Linux Polkit 权限提升漏洞(CVE-2021-4034) 0x00 前言 polkit是一个授权管理器,其系统架构由授权和身份验证代理组成,pkexec是其中polkit的其中一个工具,他的作用有点类似于sudo&#x…...

【React全家桶】React Hooks

React Hookshooks介绍useState(保存组件状态)useEffect()useCallback(记忆函数)useMemo() 记忆组件useRef(保存引用值)useReducer()useContext(减少组件层级)自定义hookshooks介绍 在react类组件(class)写法中,有setState和生命周期对状态进…...

CLIP论文阅读

Learning Transferable Visual Models From Natural Language Supervision 利用自然语言的监督信号学习可迁移的视觉模型 概述 迁移学习方式就是先在一个较大规模的数据集如ImageNet上预训练,然后在具体的下游任务上再进行微调。这里的预训练是基于有监督训练的&am…...

华为OD机试真题Python实现【身高排序】真题+解题思路+代码(20222023)

身高排序 题目 小明今年升学到了小学一年级, 来到新班级后,发现其他小朋友身高参差不齐, 然后就想基于各小朋友和自己的身高差,对他们进行排序, 请帮他实现排序 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 输入 第一行为正整数H…...

Spring Cache的使用--快速上手篇

系列文章目录 分页查询–Java项目实战篇 全局异常处理–Java实战项目篇 完善登录功能–过滤器的使用 更多该系列文章请查看我的主页哦 文章目录系列文章目录前言一、Spring Cache介绍二、Spring Cache的使用1. 导入依赖2. 配置信息3. 在启动类上添加注解4. 添加注解4.1 CacheP…...

(三十八)MySQL是如何支持4种事务隔离级别的?Spring事务注解是如何设置的?

上次我们讲完了SQL标准下的4种事务隔离级别,平时比较多用的就是RC和RR两种级别,那么在MySQL中也是支持那4种隔离级别的,基本的语义都是差不多的 但是要注意的一点是,MySQL默认设置的事务隔离级别,都是RR级别的&#x…...

【博学谷学习记录】大数据课程-学习第八周总结

Hadoop初体验 使用HDFS 1.从Linux本地上传一个文本文件到hdfs的/目录下 #在/export/data/目录中创建a.txt文件,并写入数据 cd /export/data/ touch a.txt echo "hello" > a.txt #将a.txt上传到HDFS的根目录 hadoop fs -put a.txt /2.通过页面查看…...

go cobra初试

cobra开源地址 https://github.com/spf13/cobra cobra是什么 Cobra is a library for creating powerful modern CLI applications. Cobra is used in many Go projects such as Kubernetes, Hugo, and GitHub CLI to name a few. This list contains a more extensive lis…...

【react全家桶】 事件处理

文章目录03 【事件处理】1.React事件2.类式组件绑定事件3.向事件处理程序传递参数4.收集表单数据5.受控和非受控组件5.函数的柯里化03 【事件处理】 React的事件是通过onXxx属性指定事件处理函数 React 使用的是自定义事件,而不是原生的 DOM 事件 React 的事件是通过…...

RabbitMQ交换机(Exchanges)

目录 一、概念 二、临时队列 三、绑定 四、Fanout(扇出交换机) (一)介绍 (二)实战 五、Direct(直接交换机) (一)介绍 (二)实…...

2023年java初级面试题10道基础试水题

1、面向对象的特征有哪些方面?答:面向对象的特征主要有以下几个方面:1)抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节…...

烙铁使用方法

烙铁使用 烙铁是硬件工程师最经常使用的工具之一,一把性能保持良好的烙铁能帮助我们快速进行电路调试。烙铁第一次加热时采用焊锡均匀涂覆在烙铁头上,以便去除包在烙铁头上面的氧化物。在工作中我们需要根据情况选择合适的烙铁头类型,合适的温度进行操作。完成焊接后要在烙铁…...

golang日期转换、日期增减计算、时间戳转换

// 固定日期格式format : "2006-01-02 15:04:05"// 按本地时区解析日期location, _ : time.ParseInLocation(format, "2022-02-20 11:30:00", time.Local)// 增加1年,三个参数分别是:年,月,日date : location…...

Android 多种支付方式的优雅实现

场景App 的支付流程,添加多种支付方式,不同的支付方式,对应的操作不一样,有的会跳转到一个新的webview,有的会调用系统浏览器,有的会进去一个新的表单页面,等等。并且可以添加的支付方式也是不确…...

算法设计与分析期末考试复习(三)

动态规划 动态规划算法与分治法类似,其基本思想也是将待求解问题分成若干个子问题。但是经分解得到的子问题往往不是互相独立的。在用分治法求解时,有些子问题被重复计算机了许多次。 如果能够保存已解决的子问题的答案,而在需要时再找出已求…...

ZCMU--1970: 潜伏者

Description R 国和 S 国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。  历尽艰险后,潜伏于 S 国的 R 国间谍小 C 终于摸清了 S 国军用密码的编码规则:  1. S 国军方内部欲发送的原信息经过加…...

containerd安装配置

containerd基本使用命令 containerd安装 容器运行时containerd安装配置 https://blog.csdn.net/rendongxingzhe/article/details/124595415 yum list | grep containerd containerd的本地CLI工具ctr命令 containerd的组件 containerd提供包括容器的运行、测试、发布和接口…...

随机森林算法(Random Forest)R语言实现

随机森林1. 使用Boston数据集进行随机森林模型构建2. 数据集划分3.构建自变量与因变量之间的公式4. 模型训练5. 寻找合适的ntree6. 查看变量重要性并绘图展示7. 偏依赖图:Partial Dependence Plot(PDP图)8. 训练集预测结果1. 使用Boston数据集进行随机森…...

干货 | 八条“黄金规则”解决RF电路寄生信号

PART 01 接地通孔应位于接地参考层开关处流经所布线路的所有电流都有相等的回流。耦合策略固然很多,不过回流通常流经相邻的接地层或与信号线路并行布置的接地。在参考层继续时,所有耦合都仅限于传输线路,一切都非常正常。不过,如…...

Java虚拟机之类加载学习总结

文章目录1 什么是类加载1.1 类加载的应用1.2 类加载过程1.3 类的验证1.4 类初始化顺序2 类加载时机3 类加载器3.1 类加载分类3.2 双亲委派3.3 自定义类加载器3.4 类加载器的命名空间4 打破双亲委派4.1 线程上下文类加载器4.2 自定义类加载器5 类的卸载1 什么是类加载 Java 虚拟…...

基于 vue3、vite、antdv、css 变量实现在线主题色切换

1、前言动态切换主题是一个很常见的需求. 实现方案也有很多, 如:编译多套 css 文件, 然后切换类名(需要预设主题, 不够灵活)less 在线编译(不兼容 ie, 性能较差)css 变量(不兼容 ie)但是这些基本都是针对 vue2 的, 我在网上并没有找到比较完整的解决 vue3 换肤的方案, 大多只处…...

“笨办法”学Python 3 ——练习 44 继承和组合

练习44 继承和组合 永远记住这一点:继承的大多数用法都可以用组合(composition)来简化或替换。并且无论如何都要避免多重继承。 内容提要: 1. 什么是继承? (1)隐式继承 (2&#x…...

绕过安全狗拦截的SQL注入

目录 靶场环境及中间件 知识补充 判断存在注入 整形get类注入 字符型GET注入...

JAVA练习62-无重复字符的最长子串、最长回文子串

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目1-无重复字符的最长子串 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 二、题目2-最长回文子串 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总…...

【JavaWeb】复习重点内容

✅✅作者主页:🔗孙不坚1208的博客 🔥🔥精选专栏:🔗JavaWeb从入门到精通(持续更新中) 📋📋 本文摘要:本篇文章主要分享JavaWeb的学习重点内容。 &a…...

基于粒子群改进的灰色神经网络的时间序列预测,PSO-GNN模型,神经网络案例之20

目标 灰色模型原理 神经网络原理 灰色神经网络原理 粒子群算法的原理 粒子群改进灰色神经网络原理 粒子群改进灰色神经网络的代码实现 效果图 结果分析 展望 灰色模型 基本思想是用原始数据组成原始序列(0),经累加生成法生成序列(1),它可以弱化原始数据的随机性,使其呈现…...

Java中的反射使用

1、获取Class对象的三种方式 1、对象调用Object类的getClass()方法(对象.getClass()) 2、调用类的class属性(类名.class) 3、调用Class类的静态方法(Class.forName(“包名.类名”))常用 Student类 package…...

urho3d工具

AssetImporter 加载开放资源导入库支持的各种三维格式(http://assimp.sourceforge.net/)并保存Urho3D模型、动画、材质和场景文件。有关支持的格式列表,请参阅http://assimp.sourceforge.net/main_features_formats.html. Blender的另一种导出路径是使用Urho3D插件…...