js截取数组slice(),splice()两种方法
理清JS中的深拷贝与浅拷贝
(1).浅拷贝是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变
(2).深拷贝则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
实现深拷贝:
- Object.assign() 只可以处理第一层的深拷贝。
- var objectIsNew = JSON.parse(JSON.stringify(objectIsOld));
- jQuery.extend(true, {}, objectIsOld);
reduces函数里面的return为什么要加上…state
(1)…state防止覆盖其他reducers函数返回的state
(2)…state属于浅拷贝
es6之扩展运算符 三个点(…)
我们知道javascript中有两种数据类型,分别是基础数据类型和引用数据类型。
基础数据类型 是按值访问的,常见的基础数据类型有Number
、String
、Boolean
、Null
、Undefined
,这类变量的拷贝的时候会完整的复制一份;
引用数据类型比如Array,在拷贝的时候拷贝的是对象的引用,当原对象发生变化的时候,拷贝对象也跟着变化
为Object对象动态添加属性和值
var obj = {}; //或者 var obj=new Object();
var key = "name";
var value = "张三丰"
obj[key] = value;
console.info(obj);
从一道题浅说 JavaScript 的事件循环
//请写出输出内容
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
*/
宏任务
(macro)task(又称之为宏任务),可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。
浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下:
(macro)task->渲染->(macro)task->…
(macro)task主要包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)
微任务
microtask(又称为微任务),可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。
所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。
microtask主要包含:Promise.then、MutaionObserver、process.nextTick(Node.js 环境)
运行机制
1.执行一个宏任务(栈中没有就从事件队列中获取)
2.执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
3.宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
4.当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
5.渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
等价于
async function async1() {
console.log('async1 start');
Promise.resolve(async2()).then(() => {
console.log('async1 end');
})
}
Promise.resolve(()=>{console.log('立即执行');}).then(() => {
console.log('加入微任务队列之后运行');
})
理解 JavaScript 的 async/await
async function testAsync() {
return "hello async";
}
const result = testAsync();
console.log(result);
// log 输出:Promise { 'hello async' }
async 函数返回的是一个 Promise 对象。从文档中也可以得到这个信息。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。
async 函数返回的是一个 Promise 对象,所以在最外层不能用 await 获取其返回值的情况下,我们当然应该用原来的方式:then() 链来处理这个 Promise 对象,就像这样
testAsync().then(v => {
console.log(v); // 输出 hello async
});
现在回过头来想下,如果 async 函数没有返回值,又该如何?很容易想到,它会返回 Promise.resolve(undefined)。
在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句,等到async 函数执行完成之后将结果传递到then()链。
await
- 如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
- 如果它等到的是一个 Promise 对象,await 会阻塞后面的代码,等着 Promise 对象 resolve,然后得到
resolve 的值,作为 await 表达式的运算结果。
JS中的async/await的用法和理解
this
箭头函数的this总是指向定义时所在的对象,而不是调用时。
js如何将小数保留一位且不实现四舍五入!
1 function avg(a,b){
2 var res= parseInt((a/b)*10)/10;//保留两位、三位小数 同理
3 return res;
4 }
5 console.log(avg(2,3));//输出结果为0.6
js 中编码(encode)和解码(decode)的三种方法
module.exports中引用内部函数
module.exports = {
getCursor: (rec) => Buffer.from(rec.toString()).toString("base64"),
getOffsetCustom: (data, afterCursor) => {
const offsetBasedOnFind = data.findIndex(rec =>
module.exports.getCursor(rec.id) === afterCursor
// ^^^^^^^^^^^^^^^
);
return offsetBasedOnFind === -1 ? 0 : offsetBasedOnFind + 1;
},
};