独书先生 Menu

callback Promise async 对比

需求

用最简单的示例,对比callback/Promise/async之间的演进对比,理解了callback和Promise的用法,更能体会async的方便之处,且现在推荐都使用async或者Promise和async混合使用

代码

//callback
function callbackFunc(x, callback) {
  f1(x, (err1, result1) => {
    if (err1) {
      console.error(err1);
      callback(err1);
      return;
    }
    f2(result1, (err2, result2) => {
      if (err2) {
        console.error(err2);
        callback(err2);
        return;
      }
      console.log(result2);
      callback(null, result2);
    });
  });
}

//Promise
function promiseFunc(x) {
  return f1(x)
    .then(result1 => {
      return f2(result1);
    })
    .then(result2 => {
      console.log(result2);
      return result2;
    })
    .catch(err => {
      console.error(err);
      throw err;
    });
}

//async
async function asyncFunc(x) {
  try {
    const result1 = await f1(x);
    const result2 = await f2(result1);
    console.log(result2);
    return result2;
  } catch (err) {
    console.error(err);
    throw err;
  }
}

HTML通用组件模板:自定义checkbox样式

需求

原生的checkbox样式很单一,常常需要自定义样式

方式一

使用label关联input[checkbox],input隐藏,label覆盖input显示,设置label选中前后的样式即可。

HTML:

<div class="cbk-tubiao-con">
  <input id="pro-1" class="cbk-tubiao" type="checkbox" />
  <label for="pro-1"></label>
</div>

CSS:

/*自定义checkbox*/
.cbk-tubiao-con>label:before {
    margin-top:-2px;
}
.cbk-tubiao-con {
    height:20px;
    position:relative;
}
.cbk-tubiao-con>label {
    line-height:20px;
}
.cbk-tubiao-con>label:before {
    box-sizing:border-box;
    display:inline-block;
    content:"";
    width:24px;
    height:24px;
    border-radius:50%;
    background:url("http://p31rkzyhv.bkt.clouddn.com/unchoose.png") no-repeat;
    background-size:100%;
    position:absolute;
    top:0;
    left:0;
}
input.cbk-tubiao {
    width:24px;
    height:24px;
    visibility:hidden;
    vertical-align:middle;
}
.cbk-tubiao-con input.cbk-tubiao:checked + label:before {
    content:"";
    background:url("http://p31rkzyhv.bkt.clouddn.com/choose.png") no-repeat;
    text-align: center;
}

把css中的background换成自己的图片即可

方式二

我们用react演示

tsx组件

import React, { useState } from "react";
import styles from "./Checkbox.module.css";

interface Props {
  className?: string;
  onChange?: (state: boolean) => void;
  style?: React.CSSProperties;
  children?: React.ReactNode;
  checked?: boolean;
}

export const Checkbox: React.FC<Props> = ({
  className,
  onChange,
  children,
  style = {},
  checked,
}) => {
  let [checkedState, setCheckedState] = useState(checked || false);

  const handleChange = () => {
    onChange(!checkedState);
    setCheckedState(!checkedState);
  };

  return (
    <label className={styles.container}>
      {children}
      <input type="checkbox" onChange={handleChange} checked={checkedState} />
      <span className={styles.checkmark}></span>
    </label>
  );
};

对应的样式

/* The container */
.container {
  position: relative;
  padding: 0 1em 0 1.4em;
  cursor: pointer;
  font-size: 16px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

/* Hide the browser's default checkbox */
.container input {
  position: absolute;
  opacity: 0;
  cursor: pointer;
  height: 0;
  width: 0;
}

/* Create a custom checkbox */
.checkmark {
  position: absolute;
  top: 0;
  left: 0;
  height: 1.1em;
  width: 1.1em;
  background-color: gray;
}

/* On mouse-over, add a grey background color */
.container:hover input ~ .checkmark {
  background-color: lightgary;
}

/* When the checkbox is checked, add a blue background */
.container input:checked ~ .checkmark {
  background-color: #2196f3;
}

/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
  content: "";
  position: absolute;
  display: none;
}

/* Show the checkmark when checked */
.container input:checked ~ .checkmark:after {
  display: block;
}

/* Style the checkmark/indicator */
.container .checkmark:after {
  left: 0.4em;
  top: 0.1em;
  width: 0.3em;
  height: 0.7em;
  border: solid white;
  border-width: 0 0.1em 0.1em 0;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}

js按值传递和按引用传递的区别 | 坑点提示

1.概念

按值传递: 函数内参数的值被改变,不影响外部的变量
按引用传递: 函数内参数的值被改变,影响外部的变量

2.例子

(1)按值传递

var a = 1;
function foo(x) {
x = 2;
}
foo(a);
console.log(a); // 仍为1, 未受x = 2赋值所影响

(2)按引用传递

var obj = {x : 1};
function foo(o) {
    o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, 被修改了!

3.坑点提示

var foo = {name:'foo'};
function test(o){
   o = {name:'bar'};  
}
test(foo);
console.log(foo.name); // 'foo',没有被修改

分析

本来foo传入test方法,是可以在方法内部修改foo的属性的,但是在内部直接对形参o重新赋值了一个新的对象{name:’bar’},而对象赋值给o其实是赋值这个对象的地址,等于是把形参o的地址引用链接到了{name:’bar’},而此次赋值之前o是链接到外部foo对象上的,此操作等于是断开了o与foo对象的关系,所以并没有对foo造成修改。
所以,要想修改foo内部属性值,必须使用上述按引用传递的例子,使用 对象.属性 = 'XXX'的方式,如:o.name = 'bar'

参考自:https://www.cnblogs.com/QingChengFE/p/4543608.html,感谢!

js比较Map集合取值和Array循环取值的速度差异

问题

js新的数据类型Map集合,具有数组和对象的优点,不清楚Map的同学,先移步 ES6之Map的用法
但是在使用set方法取值的时候,是否比使用数组的循环取值要快呢?理论上来说,直接取key/value是高性能的,如果在不探究深层次js解析机制的情况下,我们可以通过简单的测试函数来打印出Map取值和for循环的性能比较。

代码

let arr=[];
let arrLength = arr.length = 10000;
for(let i=0;i<arrLength;i++){
    arr[i] = i //arr为一个长度为10000的数组,0-10000
}

let m = new Map()
for(let j=0;j<arrLength;j++){
    m.set(arr[j],arr[j])//m为一个长度为10000的Map集合,key:0-10000,value:0-10000
}



//以下开始比较运行时间/
let rs = arrLength-1;
//取10000次的Map,统计时间
console.time();
for(let c=0;c<arrLength;c++){
    m.get(rs)
}

console.timeEnd();

//取10000次的arr,统计时间
console.time();
for(let c=0;c<arrLength;c++){
    arr.some((c,i,a)=>{ //数组只能用
        return  i == rs
    })
}
console.timeEnd();

结果

default: 1.3701171875ms
default: 3215.39013671875ms

分析

可以看到,Array.some在最大的循环次数下,比Map取值满了2000多倍;
实际工作场景中,取随机key的情况下,也有大概100倍至200倍的速度差异;
即使每次数组取得第一个元素不用“循环”,也有10倍的性能差异,将上述代码中let rs = arrLength-1;改成 let rs = 0;即可体验到。

而且在现在流行各大前端框架中,Map集合是可以被循环渲染到HTML模板中的,类似于 let item of items 此种用法一样对Map集合有效,所以可以放心使用。

原文:https://appsoftea.com/zh/javascript-map-set-vs-array-loop/

js颜色改变深浅 判断浅色自动加深

需求

工作中的需求,动态获取页面中的一个颜色值,应用到另一个元素的背景上,这样保持页面元素的颜色搭配比较统一。

难点

颜色值可以用户任意定义的,但是应用元素的文字字体颜色是固定白色的,这样如果用户定义的是浅色,那么应用元素的背景设置为浅色这个元素的文字就会看不清楚,如下

文字内容

方案

为了白色文字可以看清楚,考虑把浅色背景统一加深处理,已是深色不处理
Continue reading…

前端模块化总结 CommonJS/AMD/UMD/ES6

Function 时代

JSP项目中,直接在网页上添加一个script,jQuery写交互逻辑

优点:简单快速搭建demo

缺点:混乱,污染全局

例子一:

jQuery:

$(function(){

    // do something

});

或者

$(document).ready(function(){

    //do something

})

例子二:

JS:

document.ready(function () {

    alert('im document.ready');

});

window.onload = function () {

    alert('im window.onload');

};

 

闭包时代

用立即执行函数包裹作用域,

优点:可以防止全局污染;

缺点:变量常驻内存会消耗内存

 
例子一:

(function(){

    //Coding…

})()

例子二:

outObj  作为参数传递过去,不用每个语句都去找outObj,提高了效率

(function(outObj){

    var  a = 1;

    var  obj ={ b:2};

    window.obj = obj;

    return obj;

})( outObj)

 

例子三:常驻内存

function f1(){

    var n =9;

    nAdd=function(){

        n=n+1;

    }

    function f2(){

        console.log(n);

    }

    return f2;

}

var result=f1();

result(); //9

nAdd();

result();//10

注意点:全局变量不用了记得置为null,方便垃圾回收

 

 

模块化时代

CommonJS, AMD, CMD, UMD, ES6 规范(CMD已经淘汰)

 

CommonJS 规范

基本知识:
– require : 导入模块
– module.exports 或exports :导出模块

特点:
同步加载,依赖通过每个require一个个导入

例:

文件名: foo.js

// 依赖
var $ = require('jquery');

// 方法
function myFunc(){};
// 暴露公共方法(一个)
module.exports = myFunc;

注意点:

  1. exports 是对 module.exports 的引用
  2. 一个文件不能写多个module.exports ,如果写多个,对外暴露的接口是最后一个module.exports
  3. 模块如果没有指定使用module.exports 或者exports 对外暴露接口时,在其他文件就引用该模块,得到的是一个空对象{}

案列:

example1.js 文件

// 定义有依赖的模块

//CommonJS
var example2Obj = require('./example2');
example2Obj.sayHello();
module.exports = example2Obj;

 

example2.js 文件

//没有依赖的js
CommonJS
var me = {
        sayHello:function(){
        console.log('我是example2 in CommonJS!');
    }
};
module.exports = me;

main.js

//CommonJS / AMD
var example1Obj = require('./assets/example1');

console.log("example1 in main",example1Obj)

AMD 规范

基本知识:

  • define 或者 require():导入模块

  • return:导出模块

实际上也是一个闭包

define([module1,module2],function(){

    return {};

});

特点:异步加载,不阻塞页面的加载,通过define导入多个模块,

案例:

example1.js 文件

//AMD

define([
'./example2'
],function(example2Obj){
    example2Obj.sayHello();
    return example2Obj;
});

example2.js 文件

//AMD
define([
],function(){
    var we = {};
    return {
        sayHello:function(){
            console.log('我是example2 in AMD!');
        }
    };
});

main.js同CommonJS

UMD 规范

结合AMD + CommonJS的写法

(demo不生效,不举例了,有实验成功的童鞋分享下)

(function (root, factory) {

    if (typeof define === 'function' && define.amd) {

    // AMD

    define(['b'], factory);

    } else if (typeof module === 'object' && module.exports) {

    // CommonJS

    module.exports = factory(require('b'));

} else {

    // Browser globals

    root.returnExports = factory(root.b);

    }

}(this, function (b) {

    //use b in some fashion.

return {};

}));

ES6 规范

基本知识:
– import  导入
– export 或者 export default 导出

注意点:一个文件即模块中只能存在一个export default语句,export可以多个

案例:
example1.js 文件

//ES6
//名字任意
import ex2 from "./example2"
let ex1 = "ex1 ES6!!"
export {ex1,ex2}

example2.js 文件

//ES6
const str = "First ES6";
let obj = {
    func:() => {
        console.log("I am in ES6")
    }
}
//只能一个default
export default{
    str,
    obj
}

main.js

//ES6
import {ex1,ex2} from './assets/example1'
console.log("ex1:",ex1,"ex2:",ex2)

demo源代码见:https://github.com/Dushusir/js-module-demo

演示环境:vue + webpack

  1. 安装node
npm install -g vue-cli
vue init webpack myDemo
  1. cd myDemo

  2. npm run dev

  3. 去除eslint检查,防止对 “;” 报错:config/index.js中

module.exports = {

dev: {

//其他设置

useEslint: false,

参考:https://webpack.toobug.net/zh-cn/chapter2/commonjs.html ,感谢!

编写一个函数,将除最后四个字符之外的所有字符都改为’#’

codewars在线编程练习总结:信用卡数组隐藏

问题:编写一个函数maskify,它将除最后四个字符之外的所有字符都改为’#’。

列子:

maskify("4556364607935616") == "############5616"
maskify( "64607935616") == "#######5616"
maskify( "1") == "1"
maskify( "") == ""
maskify("Skippy") == "##ippy"
maskify("Nananananananananananananananana Batman!") == "####################################man!"

Continue reading…

js实现 Excel通配符比较两个字符串

需求分析:

a 与 b比较(a和b可为字符串或数字),其中b的内容比较丰富,开头可含比较符(>, >=, <, <=, =),任意位置可含通配符(Excel规则:   ?  ~  ~?), 返回Boolean(true or false)

通配符规则:

?(问号)

任何一个字符
例如,sm?th 可找到“smith”和“smyth”
*(星号) 任意的数量字符
例如,*east 可找到“Northeast”和“Southeast”
~(波形符)后跟 ?、* 或 ~

问号、星号或波形符
例如,fy06~? 可找到“fy06?”

通配符的使用详细参照Excel官网
Continue reading…