-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript实际使用中的细节记录 #223
Comments
for循环比forEach做break和return方便一些
举个例子: forEach适用于遍历整个数组,对于精确的条件控制并不适用(若想控制,需要将加入辅助变量)// 这种写法报错
[1,2,3].forEach((item)=>{
if(item===2) break ;
console.log(item);
}) => SyntaxError: Illegal break statement [1,2,3].forEach((item)=>{
if(item===2) return ;
console.log(item);
}) => 1 3 (这个三其实你并不是想打印出来) 上面这种写法常用与函数中的return。 function test() {
[1,2,3].forEach((item)=>{
if(item===2) return;
console.log(item);
})
} => 1 3(这个三其实你并不是想打印出来) for就没这烦恼,想break就break,想return就returnconst arr = [1,2,3];
for(let i = 0;i<arr.length;i++){
if(arr[i]===2) break ;
console.log(arr[i]);
} => 1 const arr = [1,2,3];
for(let i = 0;i<arr.length;i++){
if(arr[i]===2) return ;
console.log(arr[i]);
} => SyntaxError: Illegal return statement function test() {
const arr = [1,2,3];
for(let i = 0;i<arr.length;i++){
if(arr[i]===2) return;
console.log(arr[i]); // 1
}
}
let arr = [1,2,3];
for(let i of arr){
if(i===2) break ;
console.log(i); // 1
} => 1 forEach中的return, 相当于for与continue(label)的组合[1,2,3].forEach((item)=>{
if(item===2) return ;
console.log(item);
}) => 1, 3 const arr = [1,2,3];
for(let i = 0;i<arr.length;i++){
if(arr[i]===2) continue;
console.log(arr[i]);
} => 1, 3 |
过滤出存在至少一个mqtt协议的条目let protocols = [["http","https"], ['mqtts', 'tcp'],['ws', 'wss', 'https']]
let mqttProtocols = ['mqtt', 'mqtts', 'tcp', 'tls', 'ws', 'wss', 'wxs' , 'alis']
const validProtocols = protocols.filter((item)=>item.some((e)=>mqttProtocols.includes(e)))
JSON.stringify(validProtocols) // "[[\"mqtts\",\"tcp\"],[\"ws\",\"wss\",\"https\"]]" |
实现一个sleep函数,并且每隔1秒打印出心形的一行const heart = [" ***** *****"," ******* *******", "******************", " **************", " **********", " ****"] function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function heart(){
let arr = [" ***** *****"," ******* *******", "******************", " **************", " **********", " ****"];
for(const item of arr){
console.log(`%c ${item}`, 'color: red');
await sleep(1000);
}
}
await heart(); |
小数取整位操作符(为了读懂别人的代码,不建议使用)console.log(~~ 6.45) // 6
console.log(6.45 >> 0) // 6
console.log(6.45 << 0) // 6
console.log(6.45 | 0) // 6
// >>>不可对负数取整
console.log(6.45 >>> 0) // 6 parseInt(推荐使用,可读性好)parseInt(6.45) // 6
parseInt(6.54) // 6 |
十六进制色转RGB(A)方便调整透明度UI经常会给一个十六进制色,后面跟一个透明度。 function hexColorToRGB(hexColor, alpha){
let hexData = hexColor.split("");
if (hexData.length === 4) {
hexData = hexData.reduce((acc, cur) =>
cur === "#" ? [...acc, cur] : [...acc, cur, cur]
);
}
const rgbData = [];
let i = 1;
while(i < hexData.length){
const num = parseInt(`0x${hexData[i]}${hexData[i + 1]}`)
rgbData.push(num)
i = i + 2
}
if(alpha){
return `rgba(${rgbData[0]}, ${rgbData[1]}, ${rgbData[2]}, ${alpha})`
}
return `rgb(${rgbData[0]}, ${rgbData[1]}, ${rgbData[2]})`
}
hexColorToRGB("#0288D1")
hexColorToRGB("#ffffff", 0.16) |
await一个promise异常如何捕获?let promise = () => {
return new Promise((resolve, reject) => {
if (Math.random() > 0.5) {
resolve("foo");
} else {
reject("bar");
}
});
};
async function test() {
let a = await promise().catch((e) => console.log("catch", e));
console.log(a);
} 拓展1.如果没有做catch处理,console.log("hello world")会执行到吗? await promise()
console.log("hello world") // 打印出hello world 2.reject后面的代码console.log("baz")会执行吗? let promise = () => {
return new Promise((resolve, reject) => {
reject("bar");
console.log("baz")
});
};
await promise() |
计算属性不仅仅可用于拼接,还可以用于逻辑计算三元表达式let key = '';
let obj = {
[key? 'foo': 'bar']: 'value'
} obj {bar: 'value'} 或let key = '';
let obj = {
[key || 'bar']: 'value'
} obj {bar: 'value'} |
Object.is与==和===有什么不同?React中的浅比较是基于Object.is实现的。 Object.is与====在比较两边的值之前,会先进行强制转换。而Oject.is不会 Object.is与======会将-0和+0当做相等的,将Number.NaN和NaN当做不相等的。而Oject会将其看做相当的 |
如何实现一个浅比较?function shallowEqual(objA, objB) {
if (Object.is(objA, objB)) {
return true;
}
if (objA === null || typeof objA !== 'object' || objB === null || typeof objB !== 'object') {
return false
}
const keysA = Object.keys(objA)
const keysB = Object.keys(objB)
if (keysA.length !== keysB.length) {
return false
}
for (let i = 0; i < keysA.length; i++) {
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
return false
}
}
return true;
} 浅比较中的“浅”代表什么意思?若对象属性值的引用相同,则不再深入比较,认为其是相等的。 let shared = {c: 1}
let obj = {
a: 1,
b: shared
}
let obj1 = {
a: 1,
b: shared
}
console.log(shallowEqual(obj, obj1)) // true
let obj2 = {
a: 1,
b: {c: 1}
}
let obj3 = {
a: 1,
b: {c: 1}
}
console.log(shallowEqual(obj2, obj3)) // false ===等同于浅比较吗?不是。 let shared = {c: 1}
let obj = {
a: 1,
b: shared
}
let obj1 = {
a: 1,
b: shared
}
obj === obj1 // false
shallowEqual(obj1, obj1) // true 浅比较,深比较,浅复制,深复制的核心是什么核心是引用和全部。 浅比较:引用比较 浅复制:复制引用 浅:性能好 |
proxy方式的属性监听(watch)// proxy watch
let onWatch = (obj, setBind, getLogger) => {
let handler = {
get(target, property, receiver) {
getLogger(target, property)
return Reflect.get(target, property, receiver);
},
set(target, property, value, receiver) {
console.log('set', value);
setBind(value);
return Reflect.set(target, property, value);
}
};
return new Proxy(obj, handler);
};
let obj = { a: 1 }
let value
let p = onWatch(obj, (v) => {
value = v
}, (target, property) => {
console.log(`Get '${property}' = ${target[property]}`);
})
// p.a = 2 // bind `value` to `2`
// p.a // -> Get 'a' = 2
let arr = [1,2,3]
let parr = []
let p1 = onWatch(arr, (v) => {
parr.push(v)
}, (target, property) => {
console.log(`Get '${property}' = ${target[property]}`);
})
// p1.push(1)
p1[0] = 9
p1 |
encodeURI vs encodeURIComponentvar set1 = ";,/?:@&=+$#"; // Reserved Characters
var set2 = "-_.!~*'()"; // Unreserved Marks
var set3 = "ABC abc 123"; // Alphanumeric Characters + Space
console.log(encodeURI(set1)); // ;,/?:@&=+$#
console.log(encodeURI(set2)); // -_.!~*'()
console.log(encodeURI(set3)); // ABC%20abc%20123 (the space gets encoded as %20)
console.log(encodeURIComponent(set1)); // %3B%2C%2F%3F%3A%40%26%3D%2B%24%23
console.log(encodeURIComponent(set2)); // -_.!~*'()
console.log(encodeURIComponent(set3)); // ABC%20abc%20123 (the space gets encoded as %20) 对于XMR方式的HTTP请求 GET,POST来说,encodeURI不会转码;,/?:@&=+$#字符,会把它们当做特殊字符。但是encodeURIComponent会转码,比如在输入邮箱的场景中,可能需要encodeURIComponent去对邮箱做转码,同时也需要服务端做响应的解码。 |
Function.prototye.bind()怎么用bind函数运行后,会生成一个新的函数。新函数内部的this,会指向为bind的第一个参数。 const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42 这个例子中,bind的第一个参数为module,因此调用module.getX.bind(module)时,getX函数内部的this才能指向module,否则module.getX(), this指向的是window。 koa框架的中间件实现原理,也运用到了bind函数:用于返回一个全新的dispatch函数并且入参i要初始化为i+1。 function compose (middleware) {
return function (context, next) {
return dispatch(0)
function dispatch (i) {
let fn = middleware[i]
if (!fn) return Promise.resolve()
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
}
}
} https://github.com/koajs/compose/blob/3ff7778e8d5c6dbc156a510b09df91aa2a7dded4/index.js#L42 还有一种情况:需要将 传入参数后的函数,作为prop传递 的情况。 例如 Foo({
callback: main.bind(null, ({ isRender: true })) // bind返回一个将{ isRender: true }数据传递了下去的新函数。
});
interface IFoo {
callback?: () => void;
}
function main(props?: { isRender?: boolean }) { ... } bind返回一个传了部分参数的函数
let foo = (a, b) => {
console.log("a", a)
console.log("b", b)
}
let bindFoo = foo.bind(null, 1) // 注意,这返回的bindFoo,是一个只能接收1个参数,也就是b的函数
bindFoo(2)
// a 1 b 2
let foo = (a, b, c) => {
console.log("a", a)
console.log("b", b)
console.log("c", c)
}
let bindFoo = foo.bind(null, 1)
bindFoo(2, 3)
// a 1 b 2 c3 可以用来生成将后几个参数设为默认值的新函数 let foo = (a, b, c) => {
console.log("a", a);
console.log("b", b);
console.log("c", c);
}
let bindFoo = (input) => foo.bind(null, input, 1, 2);
bindFoo(42)(); // 假设 42 是你想绑定到 'a' 的值 |
可选链的执行过程如果没有可选链语法,下面的代码逻辑是怎样的?let nestedProp = obj.first?.second; => let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second); let target = data?.map((item) => item?.name); => let temp = data;
let target = (temp === null || temp === undefined)? undefined: temp.map((item) => item?.name) 如果不能有左侧变量赋值,如何模拟let data = [{name: 'foo'}, {name: 'bar'}];
data?.map((item) => item?.name) => let data = [{name: 'foo'}, {name: 'bar'}];
function optionalChain(src, operation) {
let temp = src;
if(temp === null || temp === undefined){
return undefined;
}
return eval(`${JSON.stringify(temp)}${operation}`);
}
optionalChain(data, '.map((item) => item?.name)'); |
e.target和e.currentTarget
<!DOCTYPE html>
<html lang="en">
<body>
<div id="parent">
parent
<div id="child">child</div>
</div>
</body>
<script>
// target是事件发生对象
// currentTarget是事件监听对象
const parent = document.getElementById("parent");
// 为parent绑定事件
// 点击child target是child, currentTarget是parent(这是因为事件冒泡)
// 点击parent target和currentTarget都是parent
parent.onclick = (e) => {
console.log(e.target);
console.log(e.currentTarget);
};
</script>
</html> |
巧用Promise.race加载2组CDN资源,使用先完成加载的CDNlet p 1= new Promise((resolve)=>{
setTimeout(()=>{console.log(1);resolve()}, 1000)
})
let p2 = new Promise((resolve)=>{
setTimeout(()=>{console.log(2);resolve()}, 2000)
})
let p3 = new Promise((resolve)=>{
setTimeout(()=>{console.log(3);resolve()}, 3000)
})
let p4 = new Promise((resolve)=>{
setTimeout(()=>{console.log(4);resolve()}, 1000)
})
await Promise.race([Promise.all([p1, p2]), Promise.all([p3, p4])])
console.log(5); // 1,4,2,5,3 |
如何清除url的query,并且获取最新的url信息通过history.pushState清除url的query,通过location获取最新的url信息。
// 当前页面是http://yourdomain.com/page
var newUrl = '/newpage'; // 只能使用相对路径或与当前源相同的绝对路径
window.history.pushState({}, '', newUrl);
// 访问更新后的location对象
console.log(location.href); // http://yourdomain.com/newpage
console.log(location.pathname); // /newpage
console.log(location.hostname); // yourdomain.com
console.log(location.protocol); // http: |
The text was updated successfully, but these errors were encountered: