小知识随手记(九):兄弟选择器(~和+)区别、forEach无法return和break的替换方法、html结构转为markdown语法、beforeunload离开当前页面提示、利用set及解构数组去重、设置函数必传参数

一、CSS选择器之兄弟选择器(~和+)

  以前还没注意,兄弟元素选择器 ~ 和 + 的区别:

  ‘+’选择器:表示某元素后相邻的兄弟元素,也就是紧挨着的,是单个的。

  ‘~’选择器:则表示某元素后所有同级的指定元素,强调所有的。

二、forEach无法return或break跳出循环的替换方法

  我们都知道for循环里要跳出整个循环是使用break,但在数组中用forEach循环如要退出整个循环使用break会报错,使用return也不能跳出循环。

  针对这个问题,可以使用数组的另外2个方法 some() 和 every(),或者是使用for循环,或者抛出异常,捕获异常。主要介绍下some和every方式

  some():当内部return true时跳出整个循环

  every():当内部return false时跳出整个循环

  顾名思义,some要找一些,找到了true就结束了,every本意要每个,必须明确不要了false才算退出。但是由于js函数在没有显式return值时会隐式return undefined,undefined转换为布尔值是false,相当于return false。所以在使用every时,必须显示return true才会查询每一个。

1、every 当内部return false时跳出整个循环;但不想跳出循环时,return true;也需要写

//every()当内部return false时跳出整个循环
let list = [1, 2, 3, 4, 5];
list.every((value, index) => {
    if(value > 3){
        console.log(value)// 4
        return false; // 跳出循环
    } else {
        console.log(value)// 1 2 3
        return true;
    }
});
list.every((value, index) => {
    if(value > 3){
        console.log(value)
        return false;
    }else{
        console.log(value)// 1
        // return true;
        // 如果没有返回值true 的话,也会跳出循环
    }
}); 
// 1
// false

2、forEach没有返回值,只针对每个元素调用func

// forEach没有返回值,只针对每个元素调用func。
let list2 = [1, 2, 3, 4, 5];
list2.forEach((value, index) => {
  if(value > 3){
    console.log(value)// 4 5
    return false;//没有返回值,ruturn false 仍向下执行,且最后返回undefined
  }else{
    console.log(value)// 1 2 3
    return true;
  }
});
VM27068:9 1
VM27068:9 2
VM27068:9 3
VM27068:5 4
VM27068:5 5
undefined

3、some 当内部return true时跳出整个循环

let list3 = [1, 2, 3, 4, 5];
list3.some((value, index) => {
  if(value === 3){
    return true;//当内部return true时跳出整个循环
  }
  console.log(value)// 1 2
});
VM27073:6 1
VM27073:6 2
true

4、map 有返回值,返回一个新的数组,每个元素为调用func的结果。

let list5 = [1, 2, 3, 4, 5];
let arr = [];
arr = list5.map((value, index) => {
  return value * 2;
});
console.log(arr, list5);
VM27113:6 (5) [2, 4, 6, 8, 10] (5) [1, 2, 3, 4, 5]

  具体也可以看下之前的博客:JS中map、forEach、filter、reduce等Array新增方法的区别

三、html结构转为markdown语法

  推荐一个比较好用的插件:to-markdown,目前已经改名叫: turndown,5.2K star,使用方便简单,感觉不错

  github地址:https://github.com/domchristie/turndown

四、当离开当前页面时给予用户提示

    mounted () {
      window.onbeforeunload=function(event){
        let e = window.event || event
        e.returnValue=("确定离开当前页面吗?")
      }
    },
    beforeDestroy () {
      window.onbeforeunload = null
    }

  需要注意的是在退出页面的时需要解绑onbeforeunload事件,否则会存在引用未清,无法回收,导致内存泄漏问题。

//方法一
 window.onbeforeunload = function(){
    return '真的要关闭此窗口吗?';
 }
 //or 方法二
 window.addEventListener("beforeunload", function(event) {
    //event.preventDefault();
    event.returnValue = "真的要关闭此窗口吗?";
 });

  在写一个需求,要求用户进入页面,返回/刷新/关闭该页面提示用户一些信息。发现在使用window.onbeforeunload的时候,必须打开调试才会生效,而且只有第一次有效,再次点击就会失效。

  在实际使用中让用户打开调试模式肯定是不可能的,后来发现出现这种情况是因为没有在该页面有任何操作,或者是操作时间间隔太短,所以不会有提示。

  打开该页面后,在该页面没有任何操作,不会有提示,在input中输入文字或者其他信息,刷新/返回/关闭该页面都会有提示;刷新/返回/关闭操作时间间隔太短有时有提示,有时没有。

  所以只有在该页面有操作,并且时间间隔大于5秒左右即会有提示

五、利用set及解构数组去重及合并对象

let a = [1,2,3,2,5,6,3,3,1]
let b = [...new Set(a)]
console.log(b, a)
// (5) [1, 2, 3, 5, 6] 
// (9) [1, 2, 3, 2, 5, 6, 3, 3, 1]

  不改变原数组。

  同理可以合并或拷贝对象(深拷贝)

const person = { name: 'David Walsh', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };

const summary = {...person, ...tools, ...attributes};
/*
Object {
  "computer": "Mac",
  "editor": "Atom",
  "eyes": "Blue",
  "gender": "Male",
  "hair": "Brown",
  "handsomeness": "Extreme",
  "name": "David Walsh",
}
*/

  拷贝对象(深拷贝)

let p1 = { name: 'David Walsh', gender: 'Male',aa: {a: 1} };
let p2 = {...p1}
p2.name = 'test'
console.log(p2, p1)
// {name: "test", gender: "Male", aa: {a: 1}} {name: "David Walsh", gender: "Male", aa: {a:1}}

  注意很多时候,我们需要解构别名:ES6中我们经常会使用对象结构获取其中的属性,但有时候会想重命名属性名,以避免和作用域中存在的变量名冲突,这时候可以为解构属性名添加别名。

const obj = { x: 1 };

// Grabs obj.x as { x }
const { x } = obj;

// Grabs obj.x as as { otherName }
const { x: otherName } = obj;

六、设置函数必传参数

  借助ES6支持的默认参数特性,我们可以将默认参数设置为一个执行抛出异常代码函数返回的值,这样当我们没有传参时就会抛出异常终止后面的代码运行。

const isRequired = () => { throw new Error('param is required'); };

const hello = (name = isRequired()) => { console.log(`hello ${name}`) };

// This will throw an error because no name is provided
hello();

// This will also throw an error
hello(undefined);

// These are good!
hello(null);
hello('David');

posted @ 2020-10-12 16:33  古兰精  阅读(295)  评论(0编辑  收藏  举报