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

【前端】手写代码输出题易错点汇总

不定期补充。

目录

  • 异步+事件循环
  • this
  • 作用域/变量提升/闭包
  • 原型/继承

异步+事件循环

const promise = new Promise((resolve, reject) => {console.log(1);console.log(2);
});
promise.then(() => {console.log(3);
});
console.log(4);
//1
//2
//4

promise.then 是微任务,它会在所有的宏任务执行完之后才会执行,同时需要promise内部的状态发生变化,因为这里内部没有发生变化,一直处于pending状态,所以不输出3。

const promise1 = new Promise((resolve, reject) => {console.log('promise1')resolve('resolve1')
})
const promise2 = promise1.then(res => {console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);
/*
promise1
1 Promise{<resolved>: resolve1}
2 Promise{<pending>}
resolve1
*/

直接打印Promise,会打印出它的状态值和参数。

const promise = new Promise((resolve, reject) => {console.log(1);setTimeout(() => {console.log("timerStart");resolve("success");console.log("timerEnd");}, 0);console.log(2);
});
promise.then((res) => {console.log(res);
});
console.log(4);
/*
1
2
4
timerStart
timerEnd
success
*/Promise.resolve().then(() => {console.log('promise1');const timer2 = setTimeout(() => {console.log('timer2')}, 0)
});
const timer1 = setTimeout(() => {console.log('timer1')Promise.resolve().then(() => {console.log('promise2')})
}, 0)
console.log('start');
/*
start
promise1
timer1
promise2
timer2
*/

代码执行过程如下:

  1. 首先,Promise.resolve().then是一个微任务,加入微任务队列
  2. 执行timer1,它是一个宏任务,加入宏任务队列
  3. 继续执行下面的同步代码,打印出start
  4. 这样第一轮宏任务就执行完了,开始执行微任务Promise.resolve().then,打印出promise1
  5. 遇到timer2,它是一个宏任务,将其加入宏任务队列,此时宏任务队列有两个任务,分别是timer1、timer2;
  6. 这样第一轮微任务就执行完了,开始执行第二轮宏任务,首先执行定时器timer1,打印timer1;
  7. 遇到Promise.resolve().then,它是一个微任务,加入微任务队列
  8. 开始执行微任务队列中的任务,打印promise2;
  9. 最后执行宏任务timer2定时器,打印出timer2;
const promise = new Promise((resolve, reject) => {resolve('success1');reject('error');resolve('success2');
});
promise.then((res) => {console.log('then:', res);
}).catch((err) => {console.log('catch:', err);
})
/*
then:success1
考察的就是Promise的状态在发生变化之后,就不会再发生变化
*/Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)
/*
1
*/

then方法接受的参数是函数,而如果传递的并非是一个函数,这就会导致前一个Promise的结果会传递下面。Promise.resolve(3) 是一个 Promise 对象,不是一个函数。所以这个参数也被忽略。

const promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('success')//状态改变}, 1000)
})
const promise2 = promise1.then(() => {//注意这是promise2throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {console.log('promise1', promise1)console.log('promise2', promise2)
}, 2000)
/*
promise1 Promise {<pending>}
promise2 Promise {<pending>}
promise1 Promise {<fulfilled>: "success"}
promise2 Promise {<rejected>: Error: error!!}
*/Promise.resolve(1).then(res => {console.log(res);//输出1return 2;//给到了最后的.then}).catch(err => {return 3;}).then(res => {console.log(res);//输出2});
/*
1   
2
*/

Promise是可以链式调用的,由于每次调用 .then 或者 .catch 都会返回一个新的 promise,从而实现了链式调用, 它并不像一般任务的链式调用一样return this。
上面的输出结果之所以依次打印出1和2,是因为resolve(1)之后走的是第一个then方法,并没有进catch里,所以第二个then中的res得到的实际上是第一个then的返回值。并且return 2会被包装成resolve(2),被最后的then打印输出2。

Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)//1

只需要记住一个原则:.then 或.catch 的参数期望是函数,传入非函数则会发生值透传。就是当它不存在。
第一个then和第二个then中传入的都不是函数,一个是数字,一个是对象,因此发生了透传,将resolve(1) 的值直接传到最后一个then里,直接打印出1。

Promise.resolve().then(() => {return new Error('error!!!')
}).then(res => {console.log("then: ", res)
}).catch(err => {console.log("catch: ", err)
})
/*
"then: " "Error: error!!!"
*/

返回任意一个非 promise 的值都会被包裹成 promise 对象,因此这里的return new Error(‘error!!!’)也被包裹成了return Promise.resolve(new Error(‘error!!!’)),因此它会被then捕获而不是catch。

const promise = Promise.resolve().then(() => {return promise;
})
promise.catch(console.err)
/*
Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
*/

这里其实是一个坑,.then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环。

Promise.reject('err!!!').then((res) => {console.log('success', res)}, (err) => {console.log('error', err)}).catch(err => {console.log('catch', err)})//error err!!!

错误直接被then的第二个参数捕获了,所以就不会被catch捕获了

Promise.resolve('1').then(res => {console.log(res)}).finally(() => {console.log('finally')})
Promise.resolve('2').finally(() => {console.log('finally2')return '我是finally2返回的值'}).then(res => {console.log('finally2后面的then函数', res)})
/* 注意一下微任务队列顺序,Promise.resolve是同步代码 因为创建了一个promise
1
finally2
finally
finally2后面的then函数 2
*/function runAsync (x) {const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))return p
}Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log(res))
/*
1
2
3
[1, 2, 3]
*/function runAsync (x) {const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))return p
}
function runReject (x) {const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x))
/*
`Error: ${x}`并不会打印,作为rejected 的原因传入
*/return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)]).then(res => console.log(res)).catch(err => console.log(err))
/*
// 1s后输出
1
3
// 2s后输出
2
Error: 2 //进入catch
// 4s后输出
4
*/function runAsync(x) {const p = new Promise(r =>setTimeout(() => r(x, console.log(x)), 1000));return p;
}
function runReject(x) {const p = new Promise((res, rej) =>setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x));return p;
}
Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log("result: ", res)).catch(err => console.log(err));
/* 虽然race只捕获一次,但settimeout回调函数输出还是有的
0
Error: 0
1
2
3
*/async function async1() {console.log("async1 start");await async2();console.log("async1 end");
}
async function async2() {console.log("async2");
}
async1();
console.log('start')
/*
async1 start
async2
start
async1 end跳出async1函数后,执行同步代码start;
在一轮宏任务全部执行完之后,再来执行await后面的内容async1 end。
await后面的语句相当于放到了new Promise中,
下一行及之后的语句相当于放在Promise.then中。
*/async function async1() {console.log("async1 start");await async2();console.log("async1 end");setTimeout(() => {console.log('timer1')}, 0)
}
async function async2() {setTimeout(() => {console.log('timer2')}, 0)console.log("async2");
}
async1();
setTimeout(() => {console.log('timer3')
}, 0)
console.log("start")
/*
async1 start
async2
start
async1 end
timer2
timer3
timer1
*/

代码的执行过程如下:

  1. 首先进入async1,打印出async1 start;
  2. 之后遇到async2,进入async2,遇到定时器timer2,加入宏任务队列,之后打印async2;
  3. 由于async2阻塞了后面代码的执行,所以执行后面的定时器timer3,将其加入宏任务队列,之后打印start;
  4. 然后执行async2后面的代码,打印出async1 end,遇到定时器timer1,将其加入宏任务队列;
  5. 最后,宏任务队列有三个任务,先后顺序为timer2,timer3,timer1,没有微任务,所以直接所有的宏任务按照先进先出的原则执行。
async function async1 () {console.log('async1 start');await new Promise(resolve => {console.log('promise1')})console.log('async1 success');return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
/*
script start
async1 start
promise1
script end
async1中await后面的Promise是没有返回值的,
也就是它的状态始终是pending状态,
所以在await之后的内容是不会执行的,包括async1后面的 .then。
*/async function async1 () {await async2();console.log('async1');return 'async1 success'
}
async function async2 () {return new Promise((resolve, reject) => {console.log('async2')reject('error')})
}
async1().then(res => console.log(res))
/*
async2
Uncaught (in promise) error
*/

如果async函数中抛出了错误,就会终止错误结果,不会继续向下执行。
如果想要让错误不足之处后面的代码执行,可以使用catch来捕获。

const async1 = async () => {console.log('async1');setTimeout(() => {console.log('timer1')}, 2000)await new Promise(resolve => {console.log('promise1')})//由于Promise没有返回值,所以后面的代码不会执行;console.log('async1 end')return 'async1 success'
} 
console.log('script start');
async1().then(res => console.log(res));
console.log('script end');
Promise.resolve(1)//值渗透.then(2).then(Promise.resolve(3)).catch(4).then(res => console.log(res))
setTimeout(() => {console.log('timer2')
}, 1000)
/*
script start
async1
promise1
script end
1
timer2
timer1
*/const p1 = new Promise((resolve) => {setTimeout(() => {resolve('resolve3');console.log('timer1')}, 0)resolve('resolve1');//状态只能改变一次resolve('resolve2');
}).then(res => {console.log(res)  // resolve1setTimeout(() => {console.log(p1)}, 1000)
}).finally(res => {console.log('finally', res)//.finally只会在promise里全执行完的时候才能收到状态
})
/*
resolve1
finally  undefined (因为还没收到resolve)
timer1
Promise{<resolved>: 'resolve1'}
*/console.log('1');setTimeout(function() {console.log('2');process.nextTick(function() {console.log('3');})new Promise(function(resolve) {console.log('4');resolve();}).then(function() {console.log('5')})
})
process.nextTick(function() {console.log('6');
})
new Promise(function(resolve) {console.log('7');resolve();
}).then(function() {console.log('8')
})setTimeout(function() {console.log('9');process.nextTick(function() {console.log('10');})new Promise(function(resolve) {console.log('11');resolve();}).then(function() {console.log('12')})
})
/*
1
7
6
8
2
4
3<-第二轮事件循环宏任务结束(输出2 4),
5<-发现有process2和then2两个微任务可以执行: 输出3 5。
9
11
10
12
*/Promise.resolve().then(() => {console.log('1');throw 'Error';
}).then(() => {console.log('2');
}).catch(() => {console.log('3');throw 'Error';
}).then(() => {console.log('4');
}).catch(() => {console.log('5');
}).then(() => {//错误已经被捕获 所以执行这个thenconsole.log('6');
});
/*
只要throw 抛出了错误,就会被catch捕获,
如果没有throw出错误,就继续执行后面的then。
1 
3 
5 
6
*/

this

function foo() {//这里定义的时候this是全局windowconsole.log( this.a );
}function doFoo() {foo();
}var obj = {a: 1,doFoo: doFoo
};var a = 2; 
obj.doFoo()
//2//---------
var a = 10
var obj = {a: 20,say: () => {console.log(this.a)}
}
obj.say() var anotherObj = { a: 30 } 
obj.say.apply(anotherObj)
//10
//10

箭头函数时不绑定this的,它的this来自原其父级所处的上下文,所以首先会打印全局中的 a 的值10。后面虽然让say方法指向了另外一个对象,但是仍不能改变箭头函数的特性,它的this仍然是指向全局的,所以依旧会输出10。
如果是普通函数,则输出20 30

function a() {console.log(this);
}
a.call(null);
//window对象
/*
如果第一个参数传入的对象调用者是null或者undefined,
call方法将把全局对象(浏览器上是window对象)作为this的值。
要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
*/var obj = { name: 'cuggz', fun: function(){ console.log(this.name); } 
} 
obj.fun()     // cuggz
new obj.fun() // undefined
var obj = {say: function() {var f1 = () =>  {console.log("1111", this);}f1();},pro: {getPro:() =>  {console.log(this);}}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
/*
1111 window对象  o是在全局执行的
1111 obj对象  obj.say(),谁调用say,say 的this就指向谁
window对象
*/var myObject = {foo: "bar",func: function() {var self = this;console.log(this.foo);  console.log(self.foo);  (function() {console.log(this.foo);  console.log(self.foo);  }());}
};
myObject.func();
//bar bar undefined bar

这个立即执行匿名函数表达式是由window调用的,this指向window 。立即执行匿名函数的作用域处于myObject.func的作用域中,在这个作用域找不到self变量,沿着作用域链向上查找self变量,找到了指向 myObject对象的self。

window.number = 2;
var obj = {number: 3,db1: (function(){console.log(this);this.number *= 4;return function(){console.log(this);this.number *= 5;}})()//立即执行
}
var db1 = obj.db1;
db1();
obj.db1();
console.log(obj.number);     // 15
console.log(window.number);  // 40
  1. 执行db1()时,this指向全局作用域,所以window.number x 4 = 8,然后执行匿名函数, 所以window.number x 5 = 40;然后返回的新 function 被赋值给 obj.db1
  2. 执行obj.db1();时,this指向obj对象,执行匿名函数,所以obj.numer * 5 = 15。
var length = 10;
function fn() {console.log(this.length);
}var obj = {length: 5,method: function(fn) {fn();arguments[0]();}
};obj.method(fn, 1);
//10 2 arguments长度为2var a = 1;
function printA(){console.log(this.a);
}
var obj={a:2,foo:printA,bar:function(){printA();}
}obj.foo(); // 2
obj.bar(); // 1
var foo = obj.foo;
foo(); // 1
/*
1. obj.foo(),foo 的this指向obj对象,所以a会输出2;
2. obj.bar(),printA在bar方法中执行,所以此时printA的this指向的是window,输出1;
3. foo(),foo是在全局对象中执行的,所以其this指向的是window,所以会输出1;
*/var x = 3;
var y = 4;
var obj = {x: 1,y: 6,getX: function() {//这个函数不是匿名函数 而是getXvar x = 5;return function() { //匿名函数this指向全局windowreturn this.x;}();},getY: function() {var y = 7;return this.y;}
}
console.log(obj.getX()) // 3
console.log(obj.getY()) // 6var a = 10; var obt = { a: 20, fn: function(){ var a = 30; console.log(this.a)} }obt.fn();  // 20obt.fn.call(); // 10(obt.fn)(); // 20/*
(obt.fn)()给表达式加了括号,而括号的作用是改变表达式的运算顺序,
而在这里加与不加括号并无影响;相当于  obt.fn(),所以会打印出 20;
*/function a(xx){this.x = xx;return this
};
var x = a(5);
var y = a(6);console.log(x.x)  // undefined
console.log(y.x)  // 6
/*
函数内部的this指向window对象。
所以 this.x = 5 就相当于:window.x = 5。
之后 return this,也就是说 var x = a(5) 中的x变量的值是window,
这里的x将函数内部的x的值覆盖了。
然后执行console.log(x.x), 也就是console.log(window.x),
而window对象中没有x属性,所以会输出undefined。
*/
function foo(something){this.a = something
}var obj1 = {}var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2var baz = new bar(3);
console.log(obj1.a); // 2
console.log(baz.a); // 3
/*
考察this绑定的优先级。记住以下结论即可:
this绑定的优先级:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定。
*/

作用域/变量提升/闭包

(function(){var x = y = 1;
})();
console.log(x); // Uncaught ReferenceError: x is not defined
/*
var x = y = 1; 实际上这里是从右往左执行的,
首先执行y = 1, 因为y没有使用var声明,所以它是一个全局变量,
然后第二步是将y赋值给x,讲一个全局变量赋值给了一个局部变量,
最终,x是一个局部变量,y是一个全局变量,所以打印x是报错。
*/var a, b
(function () {var a = (b = 3);//注意区分(b==3)console.log(a);console.log(b);   
})()
console.log(a);
console.log(b);
//3 3 undefined 3var friendName = 'World';
(function() {if (typeof friendName === 'undefined') {var friendName = 'Jack';console.log('Goodbye ' + friendName);} else {console.log('Hello ' + friendName);}
})();
//Goodbye Jack
//在 JavaScript中, Function 和 var 都会被提升(变量提升)
//注意如果是
var fn2 //只提升这个
fn2() //Uncaught TypeError: fn2 is not a function
fn2 = function() {console.log('fn2')
}function a() {var temp = 10;b();
}
function b() {console.log(temp); // 报错 Uncaught ReferenceError: temp is not defined
}
a();
//js中变量的作用域链与定义时的环境有关,与执行时无关。
//执行环境只会改变this、传递的参数、全局变量等function fun(n, o) {console.log(o)return {fun: function(m){return fun(m, n);}};
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);
/*
undefined  0  0  0
undefined  0  1  2
undefined  0  1  1
而a就是是fun(0)返回的那个对象。也就是说,函数fun中参数 n 的值是0,而返回的那个对象中,需要一个参数n,而这个对象的作用域中没有n,它就继续沿着作用域向上一级的作用域中寻找n,最后在函数fun中找到了n,n的值是0。了解了这一点,其他运算就很简单了,以此类推。
*/f = function() {return true;};   
g = function() {return false;};   
(function() {   if (g() && [] == ![]) {   f = function f() {return false;};   function g() {return true;}   //这个会被函数提升并覆盖g//由于在匿名函数中,又重新定义了函数g,就覆盖了外部定义的变量g}   
})();   
console.log(f());//false

原型/继承

function Person(name) {this.name = name
}
var p2 = new Person('king');
console.log(p2.__proto__.__proto__) //Object.prototype
console.log(p2.__proto__.__proto__.__proto__) // null
console.log(p2.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错
console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错console.log(p2.prototype)//undefined p2是实例,没有prototype属性console.log(Person.prototype)//打印出Person.prototype这个对象里所有的方法和属性
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.__proto__)// Object.prototype
console.log(Person.__proto__) //Function.prototypeconsole.log(Function.__proto__)//Function.prototype
console.log(Object.__proto__)//Function.prototype
console.log(Object.prototype.__proto__)//null// a
function Foo () {getName = function () {console.log(1);}return this;
}
// b
Foo.getName = function () {console.log(2);
}
// c
Foo.prototype.getName = function () {console.log(3);
}
// d
var getName = function () {console.log(4);
}
// e
function getName () {console.log(5);
}Foo.getName();           // 2
getName();               // 4
Foo().getName();         // 1
//执行Foo()返回 this,这个this指向window,Foo().getName() 成为window.getName()
getName();               // 1 new Foo.getName();       // 2
//等价于 new (Foo.getName())new Foo().getName();     // 3
//等价于 (new Foo()).getName(),
//先new一个Foo的实例,再执行这个实例的getName方法,但是这个实例本身没有这个方法,
//所以去原型链上边找,实例.__proto__ === Foo.prototype,所以输出 3;new new Foo().getName(); // 3
//new (new Foo().getName())
var F = function() {};
Object.prototype.a = function() {console.log('a');
};
Function.prototype.b = function() {console.log('b');
}
var f = new F();
f.a();
f.b();
F.a();
F.b()
/*
a
Uncaught TypeError: f.b is not a function
a
bF 是个构造函数,F 是构造函数 Function 的一个实例。
因为 F instanceof  Object === true,F instanceof Function === true,
由此可以得出结论:F 是 Object 和 Function 两个的实例
*/var A = {n: 4399};
var B =  function(){this.n = 9999};
var C =  function(){var n = 8888};
B.prototype = A;
C.prototype = A;
var b = new B();
var c = new C();
A.n++
console.log(b.n);
console.log(c.n);
//9999 4400
/*
在查找b.n是首先查找 b 对象自身有没有 n 属性,如果没有会去原型(prototype)上查找,当执行var b = new B()时,函数内部this.n=9999(此时this指向 b) 返回b对象,b对象有自身的n属性,所以返回 9999。
c对象没有自身的n属性,向上查找,找到原型 (prototype)上的 n 属性
*/function B(a){this.a = a;
}
B.prototype.a = 1;
console.log(new B().a);
//undefined 没传参等于传入undefinedfunction Parent() {this.a = 1;this.b = [1, 2, this.a];this.c = { demo: 5 };this.show = function () {console.log(this.a , this.b , this.c.demo );}
}function Child() {this.a = 2;this.change = function () {this.b.push(this.a);this.a = this.b.length;this.c.demo = this.a++;}
}
Child.prototype = new Parent();
var child1 = new Child();
var child2 = new Child();
child1.a = 11;
child2.a = 12;
child1.show();
child2.show();
child1.change();
child2.change();
child1.show();
child2.show();
/*
child1.show(); // 11 [1,2,1] 5
child2.show(); // 12 [1,2,1] 5
child1.show(); // 5 [1,2,1,11,12] 5
child2.show(); // 6 [1,2,1,11,12] 5
*/

后两个结果是怎么来的?
● this.b.push(this.a),由于this的动态指向特性,this.b会指向Child.prototype上的b数组,this.a会指向child1的a属性,所以Child.prototype.b变成了[1,2,1,11];
● this.a = this.b.length,这条语句中this.a和this.b的指向与上一句一致,故结果为child1.a变为4;
● this.c.demo = this.a++,由于child1自身属性并没有c这个属性,所以此处的this.c会指向Child.prototype.c,this.a值为4,为原始类型,故赋值操作时会直接赋值,Child.prototype.c.demo的结果为4,而this.a随后自增为5(4 + 1 = 5)。

child2执行了change()方法, 而child2和child1均是Child类的实例,所以他们的原型链指向同一个原型对象Child.prototype,也就是同一个parent实例,所以child2.change()中所有影响到原型对象的语句都会影响child1的最终输出结果。
● this.b.push(this.a),由于this的动态指向特性,this.b会指向Child.prototype上的b数组,this.a会指向child2的a属性,所以Child.prototype.b变成了[1,2,1,11,12];
● this.a = this.b.length,这条语句中this.a和this.b的指向与上一句一致,故结果为child2.a变为5;
● this.c.demo = this.a++,由于child2自身属性并没有c这个属性,所以此处的this.c会指向Child.prototype.c,故执行结果为Child.prototype.c.demo的值变为child2.a的值5,而child2.a最终自增为6(5 + 1 = 6)。

function SuperType(){this.property = true;
}SuperType.prototype.getSuperValue = function(){return this.property;
};function SubType(){this.subproperty = false;
}SubType.prototype = new SuperType();//原型继承的写法
//SubType构造函数变成SuperType
//只影响SubType.prototype、SubType 实例的原型链
//不会影响上面写到的 SubType()该执行执行
//this.subproperty = false; 是会赋值给新创建的实例
SubType.prototype.getSubValue = function (){return this.subproperty;
};var instance = new SubType();//instance当然是SubType的实例
console.log(instance.getSuperValue());//输出:true

在这里插入图片描述

相关文章:

【前端】手写代码输出题易错点汇总

不定期补充。 目录 异步事件循环this作用域/变量提升/闭包原型/继承 异步事件循环 const promise new Promise((resolve, reject) > {console.log(1);console.log(2); }); promise.then(() > {console.log(3); }); console.log(4); //1 //2 //4promise.then 是微任务&…...

STM32F103_HAL库+寄存器学习笔记20 - CAN发送中断+ringbuffer + CAN空闲接收中断+接收所有CAN报文+ringbuffer

导言 如上所示&#xff0c;在[[STM32F103_HAL库寄存器学习笔记19 - CAN发送中断CAN接收中断接收所有CAN报文ringbuffer数据结构]]的基础上&#xff0c;为CAN发送端也引入了ringbuffer&#xff08;环形缓冲区&#xff09;机制。CAN发送有三个发送邮箱&#xff0c;为什么还另外需…...

小白自学python第二天

学习python的第二天 一、判断语句 1、布尔类型和比较运算符 1、布尔类型 表示现实生活中的逻辑&#xff0c;真&#xff08;True&#xff0c;用数字1表示&#xff09;和假&#xff08;False&#xff0c;用数字0表示&#xff09; 2、布尔类型变量的定义 变量的名称 布尔类…...

JavaScript 异步编程与请求取消全指南

JavaScript 异步编程与请求取消全指南 涵盖&#xff1a;同步/异步、Promise、async/await、AbortController、前后端协作 一、同步与异步 1. 同步&#xff08;Synchronous&#xff09; 定义&#xff1a;代码按顺序执行&#xff0c;前一步完成才能执行下一步。特点&#xff1…...

Redis 核心应用场景

高性能缓存 Redis 作为内存数据库&#xff0c;读写性能可达10万 QPS&#xff0c;适合缓存热点数据&#xff08;如商品详情、用户会话&#xff09;&#xff0c;显著降低数据库压力。通过设置过期时间&#xff08;TTL&#xff09;自动清理非热点数据&#xff0c;推荐结合allkeys-…...

KMS工作原理及其安全性分析

在当今数字化时代&#xff0c;数据安全已经成为企业和个人最为关注的话题之一。随着云计算和大数据的快速发展&#xff0c;如何安全地管理密钥成为了一个重要的挑战。KMS&#xff08;Key Management Service&#xff0c;密钥管理服务&#xff09;作为一种专业的密钥管理解决方案…...

施磊老师基于muduo网络库的集群聊天服务器(六)

文章目录 客户端开发开始客户端首页面功能为何不逐行开发&#xff1f;客户端CMake代码搭配知识补充--有很多漏的客户端main-登录,注册,退出群组有问题测试 客户端好友添加与聊天功能表驱动设计&#xff1a;commandMapcommandHandlerMap为什么都是int, string添加好友和聊天功能…...

有关字体,语言,字符编码相关的基础知识,询问chatgpt所得

学习这个知识点的背景是&#xff0c;我需要做一个 在canvas 上书写矢量文本的功能&#xff0c; 使用opentype来加载字体文件&#xff0c;并将内容转换为 svg&#xff0c;导入画布。 但是有些字体文件 是不包含 一些其他语言的字符的。就可能出现 “无效字符”。 花了点时间研究…...

Obsidian和Ollama大语言模型的交互过程

之前的文章中介绍了Obsidian配合Ollama的使用案例&#xff0c;那么它们是如何配合起来的呢&#xff1f;其实这个问题并不准确&#xff0c;问题的准确描述应该是Obsidian的Copilot插件是如何与Ollama大语言模型交互的。因为Obsidian在这里只是一个载体&#xff0c;核心功能还是C…...

架构-数据库系统

数据库系统 一、数据库系统概述 &#xff08;一&#xff09;课程核心模块 覆盖数据库设计、关系代数、规范化理论、数据控制四大核心模块&#xff0c;旨在构建从理论到实践的完整知识体系至。 &#xff08;二&#xff09;典型应用场景 数据管理&#xff1a;学生信息管理&a…...

【C到Java的深度跃迁:从指针到对象,从过程到生态】第三模块·面向对象深度进化 —— 第十二章 接口:比C函数指针更强大的契约

一、从函数指针到接口契约 1.1 C函数指针的本质限制 C语言通过函数指针实现回调机制&#xff0c;但存在根本性缺陷&#xff1a; 回调函数示例&#xff1a; typedef void (*Logger)(const char*); void process_data(int data, Logger logger) { // ... logger("Pro…...

【HFP】蓝牙语音通话控制深度解析:来电拒接与通话终止协议

目录 一、来电拒接的核心流程与信令交互 1.1 拒接场景的分类与触发条件 1.2 HF 端拒接流程 1.3 AG 端拒接流程 二、通话终止流程&#xff1a;主动断开与异常中断 2.1 终止场景的界定 2.2 HF 端终止流程 2.3 AG 端终止流程 三、信令协议的核心要素&#xff1a;AT 命令与…...

linux 中断子系统 层级中断编程

虚拟中断控制器代码&#xff1a; #include<linux/kernel.h> #include<linux/module.h> #include<linux/clk.h> #include<linux/err.h> #include<linux/init.h> #include<linux/interrupt.h> #include<linux/io.h> #include<linu…...

continue插件实现IDEA接入本地离线部署的deepseek等大模型

文章目录 前言一、IDEA安装continue二、continue部署本地大模型三、continue聊天窗口使用deepseek R1四、continue批量接入硅基流动的模型API 前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0c;您的关注是我…...

Redis-缓存应用 本地缓存与分布式缓存的深度解析

Redis缓存场景与策略&#xff1a;本地缓存与分布式缓存的深度解析 在当今高并发、低延迟的互联网架构中&#xff0c;缓存技术是优化系统性能的核心手段之一。Redis作为分布式缓存的标杆&#xff0c;与本地缓存共同构成了缓存体系的两大支柱。然而&#xff0c;两者的适用场景与…...

关于按键映射软件的探索(其一)

那么先说结论——重构了一次&#xff0c;我还是失败了&#xff0c;失败于拓展调整个性化的设计&#xff0c;不过我还是实现了按键监测然后显示的功能。只不过是说我对于WPF软件等的封装和软窗口的功能还是不怎么熟悉。 引言 在许多游戏玩家中&#xff0c;高难度操作&#xff08…...

测试基础笔记第十一天

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、查询连接1.内连接2.左连接3.右连接4.左右连接的必要性5.自关联6.普通查询7.子查询8.子查询充当数据源 二、数据库高级扩展内容1.外键2.索引3.验证索引效果案例实…...

优选算法第十讲:字符串

优选算法第十讲&#xff1a;字符串 1.最长公共前缀2.最长回文子串3.二进制求和4.字符串相乘 1.最长公共前缀 2.最长回文子串 3.二进制求和 4.字符串相乘...

RK3588芯片NPU的使用:官方rknn_yolov5_android_apk_demo运行与解读

一、本文的目标 本文将完成两项任务: 官方的调用摄像头动态目标识别例子运行在rk3588的开发板上。解读源码以增加对rknn开发的认识。二、开发环境说明 主机系统:Windows 11目标设备:搭载RK3588芯片的安卓开发板核心工具:Android Studio Koala | 2024.1.1 Patch 2,NDK 27.…...

面试篇:Spring Boot

基础概念 Spring Boot的核心优势是什么&#xff1f; Spring Boot 的核心优势如下&#xff1a; 自动配置&#xff1a;根据项目中的依赖自动进行配置&#xff0c;减少了大量的手动配置工作。 内嵌服务器&#xff1a;内置 Tomcat、Jetty 等容器&#xff0c;应用可以直接运行为一…...

开源漏洞扫描器:OpenVAS

一、OpenVAS介绍 OpenVAS (Open Vulnerability Assessment System) 是一款功能强大的开源漏洞扫描器。它由 Greenbone Networks 开发和维护&#xff0c;是 Greenbone 安全管理器 (GSM) 产品的基础&#xff0c;同时也有免费的社区版本&#xff08;Greenbone Community Edition&…...

PCB封装主要组成元素

PCB&#xff08;Printed Circuit Board&#xff0c;印刷电路板&#xff09;封装是指将电子元件固定在 PCB 上&#xff0c;并实现电气连接的方式。主要包括以下几类。 1. 焊盘&#xff08;Pad&#xff09; 作用&#xff1a;焊盘是 PCB 封装中最重要的元素之一&#xff0c;它是…...

STC8H DMA 串口1全双工中断方式收发通讯C语言

/************* 功能说明 ************** 本例程基于STC8H8K64U为主控芯片的实验箱9进行编写测试&#xff0c;STC8H系列带DMA模块的芯片可通用参考. 串口1全双工中断方式收发通讯程序。 通过PC向MCU发送数据, MCU将收到的数据自动存入DMA空间. 当DMA空间存满设置大小的…...

考研英一学习笔记

2024 年全国硕士研究生招生考试 英语&#xff08;一&#xff09;试题 &#xff08;科目代码&#xff1a;201&#xff09; Section Ⅰ Use of English Directions: Read the following text. Choose the best word(s) for each numbered blank and mark A, B, C or D on the ANS…...

深度理解spring——BeanFactory的实现

BeanFactory Spring之BeanFactory什么是BeanFactoryApplicationContext相对BeanFactory实现的功能性扩展1. MessageSource2. ResourcePatternResolver3. ApplicationEventPublisher4. EnvironmentCapable通用ApplicationContext实践实现BeanFactoryBeanFactory后处理器排序让谁…...

半导体---检测和量测

目录 1.简介2.AOI(检测) 1.简介 半导体晶圆制造前道量测和检测设备。 公司产品涵盖光学薄膜量测、光学关键尺寸量测、光学衍射套刻量测、光学集成量测、X射线薄膜量测、X射线材料性能量测、X射线成分及表面污染量测等系列产品及解决方案。 半导体领域的量测和AOI如同半导体制造…...

CentOS 7 磁盘分区详细教程

CentOS 7 磁盘分区详细教程 在服务器管理和运维过程中&#xff0c;磁盘分区是一项基础且重要的操作。合理的磁盘分区可以提高数据存储的安全性、高效性&#xff0c;方便系统管理与维护。本文将详细介绍在 CentOS 7 系统中进行磁盘分区的具体步骤和方法。 一、准备工作 1.1 确…...

EasyRTC音视频实时通话在线教育解决方案:打造沉浸式互动教学新体验

一、方案概述 EasyRTC是一款基于WebRTC技术的实时音视频通信平台&#xff0c;为在线教育行业提供了高效、稳定、低延迟的互动教学解决方案。本方案将EasyRTC技术深度整合到在线教育场景中&#xff0c;实现师生间的实时音视频互动等核心功能&#xff0c;打造沉浸式的远程学习体…...

栈(Stack)和队列(Queue)

栈 栈&#xff08;stack&#xff09;是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除操作。 我们可以将栈近似看作一个桶&#xff0c;要取出桶底的元素&#xff0c;就要将桶顶的元素先取出&#xff0c;再将底部元素取出&#xff0c;也可以叫做后进先出。 这…...

1、AI及LLM基础:Python语法入门教程

Python语法入门教程 ​ 这是一份全面的Python语法入门教程,涵盖了注释、变量类型与操作符、逻辑运算、list和字符串、变量与集合、控制流和迭代、模块、类、继承、进阶等内容,通过详细的代码示例和解释,帮助大家快速熟悉Python语法。 文章目录 Python语法入门教程一、注释二…...

跨境电商关键词分类打标

你是一名顶级的亚马逊关键词分析专家,你将用你的亚马逊运营专业的经验帮助我做精准的关键词打标。 首先你会学习以下的知识内容,以便于你后续的关键词分析。 人群词是什么? 是指直接描述或定位特定用户群体的关键词或标签,用于精准识别目标受众的身份、需求或行为特征。 …...

C# 结构(Struct)

原文&#xff1a;C# 结构&#xff08;Struct&#xff09;_w3cschool 在 C# 中&#xff0c;结构是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构。 结构是用来代表一个记录。假设您想跟踪图书馆中书的动态。您可能想跟踪每本…...

Java Collections工具类指南

一、Collections工具类概述 java.util.Collections是Java集合框架中提供的工具类&#xff0c;包含大量静态方法用于操作和返回集合。这些方法主要分为以下几类&#xff1a; 排序操作查找和替换同步控制不可变集合特殊集合视图其他实用方法 二、排序操作 1. 自然排序 List&…...

BBRv2,v3 吞吐为什么不如 BBRv1

为什么 BBRv2/3 测试下来吞吐远不如 2016 年底的 BBRv1&#xff0c;这个事曾经提到过很多次&#xff0c;今天分析一下原理。注意三个事实&#xff1a; BBR 是一种拥塞控制算法&#xff1b;BBR 已经迭代到了 v3 版本&#xff1b;BBRv3 的 “性能” 远不如 BBRv1. 第二点有点不…...

Java集成【邮箱验证找回密码】功能

目录 1.添加依赖 2.选择一个自己的邮箱&#xff0c;作为发件人角色。 3.编写邮箱配置【配置发件人邮箱】 4.编写邮箱配置类 5.编写controller业务代码 6.演示效果 7.总结流程 8.注意 结语 1.添加依赖 <!--导入邮箱依赖--> <dependency><groupId>or…...

Java微服务架构设计与实践 - 面试实战

Java微服务架构设计与实践 - 面试实战 在互联网大厂的Java求职者面试中&#xff0c;微服务架构设计是一个常见的考察点。本文通过严肃的面试官和资深Java架构师马架构之间的对话&#xff0c;详细展示了如何回答SpringCloud相关的核心技术问题。 第一轮提问 面试官&#xff1…...

Java后端开发面试题(含答案)

在广州一个小公司&#xff08;BOSS标注是20-99人&#xff0c;薪资2-3k左右)&#xff0c;直接面试没有笔试&#xff0c;按流程自我介绍&#xff0c;然后直接拿着简历问项目场景&#xff0c;问题是结合场景题和八股文。废话不多说&#xff0c;直接分享面试题目个大家做参考。 1、…...

Sharding-JDBC 系列专题 - 第九篇:高可用性与集群管理

Sharding-JDBC 系列专题 - 第九篇:高可用性与集群管理 本系列专题旨在帮助开发者全面掌握 Sharding-JDBC,一个轻量级的分布式数据库中间件。本篇作为系列的第九篇文章,将重点探讨 高可用性(High Availability, HA) 和 集群管理,包括数据库高可用方案、Sharding-JDBC 的故…...

Node.js 学习入门指南

Node.js 学习入门指南 Node.js 是一种流行的开源、跨平台的 JavaScript 运行时环境&#xff0c;它使开发者能够在服务器端运行JavaScript代码。本篇文章旨在帮助初学者快速入门并掌握Node.js的基础知识和常用技巧。 一、什么是Node.js&#xff1f; 定义 Node.js 是一个基于…...

数智视融合驱动未来,Al+数字孪生重塑价值|2025袋鼠云春季数智发布会回顾

4月16日&#xff0c;袋鼠云成功举办了“做DataAI的长期主义者——2025年袋鼠云春季数智发布会”&#xff0c;从智能分析决策平台到AI大模型应用&#xff0c;从数字孪生中枢到AI增强型数字世界&#xff0c;勾勒出企业数智化转型的进化图谱&#xff0c;真正实现AI赋能企业业务&am…...

nfs服务原理、搭建手册、安全配置建议及异常定位手段

一、NFS服务原理 NFS&#xff08;Network File System&#xff09;是一种基于TCP/IP协议的网络文件共享系统&#xff0c;允许客户端像访问本地文件一样访问远程服务器上的共享目录。其核心原理依赖于RPC&#xff08;Remote Procedure Call&#xff09;机制&#xff0c;具体流程…...

第十三届蓝桥杯 2022 C/C++组 修剪灌木

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 核心思路&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; P8781 [蓝桥杯 2022 省 B] 修…...

MySQL:数据库设计

目录 一、范式 二、第一范式 二、第二范式 三、第三范式 四、设计 &#xff08;1&#xff09;一对一关系 &#xff08;2&#xff09;一对多关系 &#xff08;3&#xff09;多对多关系 一、范式 数据库的范式是一种规则&#xff08;规范&#xff09;&#xff0c;如果我们…...

OpenManus与OWL部署及体验报告

OpenManus与OWL对任务的执行结果均不及Manus&#xff1b;二者比较&#xff0c;Owl达成率更高&#xff1b;二者使用过程中均会消耗大量tokens&#xff0c;单个问题成本高。 一、部署 OpenManus&#xff1a;https://github.com/mannaandpoem/OpenManus.git OWL&#xff1a;https…...

【Pandas】pandas DataFrame pow

Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象&#xff08;如 DataFrame、Series 或标量&#xff09;的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...

Red:1靶场环境部署及其渗透测试笔记(Vulnhub )

环境介绍&#xff1a; 靶机下载&#xff1a; https://download.vulnhub.com/red/Red.ova 本次实验的环境需要用到VirtualBox&#xff08;桥接网卡&#xff09;&#xff0c;VMware&#xff08;桥接网卡&#xff09;两台虚拟机&#xff08;网段都在192.168.152.0/24&#xff0…...

【多源01BFS】Codeforce:Three States

题干 翻译 给定一个 nm 的网格地图&#xff0c;包含以下元素&#xff1a; .&#xff1a;表示荒地&#xff08;可以修建道路&#xff09;。 #&#xff1a;表示岩石&#xff08;不可通行&#xff09;。 数字 1、2、3&#xff1a;分别表示三个国家的位置。 目标&#xff1a;将…...

在深度学习中FLOPs和GFLOPs的含义及区别

在深度学习中&#xff0c;FLOPs和GFLOPs是衡量计算性能的关键指标&#xff0c;但两者的定义和应用场景不同&#xff1a; 1. 定义与区别 • FLOPs&#xff08;Floating-point Operations&#xff09; 表示模型或算法执行时所需的浮点运算总次数&#xff0c;用于衡量模型的计算复…...

SpringBoot入门实战(项目搭建、配置、功能接口实现等一篇通关)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 SpringBoot入门实战&#xff08;项目搭建、配…...

昆仑万维开源SkyReels-V2,解锁无限时长电影级创作,总分83.9%登顶V-Bench榜单

昆仑万维开源了全球首个基于扩散强迫框架&#xff08;Diffusion-forcing&#xff09;的无限时长视频生成模型——SkyReels-V2。这一模型以总分83.9%的优异成绩登顶权威评测V-Bench1.0榜单&#xff0c;并在质量维度获得84.7%的评分&#xff0c;刷新了开源视频生成技术的天花板。…...