杂记

css中两个类选择器之间没有空格形成多类选择器, 有空格形成后代选择器 。


CSS hover,没有延迟




<span title=”“>


css3修改滚动条样式

1.滚动条组成

::-webkit-scrollbar 滚动条整体部分

::-webkit-scrollbar-thumb 滚动条里面的小方块,能向上向下移动(或往左往右移动,取决于是垂直滚动条还是水平滚动条)

::-webkit-scrollbar-track 滚动条的轨道(里面装有Thumb)

::-webkit-scrollbar-button 滚动条的轨道的两端按钮,允许通过点击微调小方块的位置。

::-webkit-scrollbar-track-piece 内层轨道,滚动条中间部分(除去)

::-webkit-scrollbar-corner 边角,即两个滚动条的交汇处

::-webkit-resizer 两个滚动条的交汇处上用于通过拖动调整元素大小的小控件

2.简洁版demo

/定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸/

::-webkit-scrollbar 
{ 
    width: 16px;     
    height: 16px;     
    background-color: #F5F5F5; 
} 

/定义滚动条轨道 内阴影+圆角/

::-webkit-scrollbar-track 
{ 
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); 
    border-radius: 10px; 
    background-color: #F5F5F5; 
} 

/定义滑块 内阴影+圆角/

::-webkit-scrollbar-thumb 
{ 
    border-radius: 10px; 
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); 
    background-color: #555; 
} 

惰性求值

惰性求值(Lazy evaluation)是在需要时才进行求值的计算方式。惰性求值自然地在数据结构中包含递归,可以以简单的方式表示无限的概念,这种方式有利于程序的模块化。

Haskell语言以采用惰性求值而广为人熟知。Scheme也部分采用了惰性求值。


0.1 + 0.2 - 0.3

// 5.551115123125783e-17

0.1 + 0.2 === 0.3 // false


Array.prototype.slice.call()方法详解

多次用到 Array.prototype.slice.call(arguments, 1),不就是等于 arguments.slice(1) 吗?像前者那样写具体的好处是什么?这个很多js新手最疑惑的地方。那为什么呢?

因为arguments并不是真正的数组对象,只是与数组类似而已,所以它并没有slice这个方法,而Array.prototype.slice.call(arguments, 1)可以理解成是让arguments转换成一个数组对象,让arguments具有slice()方法。要是直接写arguments.slice(1)会报错。

typeof arguments===”object” //而不是 “Array”


arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。


在JavaScript中,如果你在一个函数体内又用到了function关键字,那么你将会生成一个闭包(Closure)。

闭包含有当前作用域内的所有变量接入。

每一次对外部函数的调用都会产生一个独立的包含本地变量的闭包。

闭包到底什么用

可以在函数外部读取函数内部的变量
可以将这些变量的值在内存中持久化


IIFE

IIFE(立即调用函数表达式)是一个在定义时就会立即执行的JavaScript函数。

这是一个被称为自执行匿名函数的设计模式,主要包含两部分。第一部分是包围在圆括号运算符()里的一个匿名函数,这个匿名函数拥有独立的词法作用域,这不仅避免了外界访问此IIFE中的变量,而且又不会污染全局作用域。

第二部分再使用()创建了一个立即执行函数表达式,JavaScript引擎到此将直接执行函数。


箭头函数导致this总是指向函数定义生效时所在的对象


then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行


Promise.all方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。)


then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。


创建XMLHttpRequest对象的语法:

xmlhttp = new XMLHttpRequest();

老版本的Internet Explorer(IE5和IE6)使用ActiveX对象:

xmlhttp = new ActiveXObject(“Microsoft.XMLHTTP”);


echarts: itemStyle属性要加normal属性


使用把一些兄弟元素归为一组

Angular的是一个分组元素,但它不会污染样式或元素布局,因为Angular压根不会把它放进DOM中。

是一个由Angular解析器负责识别处理的语法元素。它不是一个指令、组件、类或接口,更像是JavaScript中if块中的花括号。

没有这些花括号,JavaScript只会执行第一句,而你原本的意图是把其中的所有语句都视为一体来根据条件执行。而满足了Angular模板中类似的需求。


https://www.chungold.com/

账号 hon_ghuan1688@126.com

密码 zhnyfw@001


background-clip 属性
background-clip属性指定背景绘制区域

语法
background-clip:

border-box // 背景到border
padding-box // 背景到padding
content-box // 背景到content

background-origin属性

background-origin属性指定background-position属性应该是相对位置


background-size

第二个值,不写默认为auto


background:linear-gradient(angle …);

角度说明

0deg将创建一个从上到下的渐变,90deg将创建一个从左到右的渐变。


Internet Explorer 渐变

语法    
filter:progid:DXImageTransform.Microsoft.gradient
(startColorstr='startColor', 
endColorstr='endColor',GradientType(类型)=(0,1,2));

常见的闭包:

function wait(message) {
    setTimeout(function timer() {
        console.log(message);
    }, 1000);
}
wait('Hello closure');

只要使用了回调函数,实际上就是在使用闭包!


模块有两个主要特征:

1.为创建内部作用域而调用了一个包装函数;

2.包装函数的返回值必须至少包括一个对内部函数的引用,这样就会创建涵盖整个包装函数内部作用域的闭包。


CommonJS // module.exports require 同步

cmd // define (module.exports) require 异步


<script>标签
CommonJS
AMD(Asynchronous Module Definition)
CMD(Common Module Definition)
UMD(Universal Module Definition)
ES6模块

var request;
if (window.XMLHttpRequest) {
    request = new XMLHttpRequest();
} else {
    request = new ActiveXObject('Microsoft.XMLHTTP');
}

通过检测window对象是否有XMLHttpRequest属性来确定浏览器是否支持标准的XMLHttpRequest。注意,不要根据浏览器的navigator.userAgent来检测浏览器是否支持某个JavaScript特性,一是因为这个字符串本身可以伪造,二是通过IE版本判断JavaScript特性将非常复杂。


字符串方法

ES7提案

要安装补丁库

npm install babel-polyfill --save-dev

es6标签模板

常用场景:防止XS攻击

多语言转换

{
    let user={
        name: 'list',
        info: 'hello world'
    };
    console.log(abc`i am ${user.name},${user.info}`);
    function abc(s,v1,v2){
        console.log(s,v1,v2);
        return s+v1+v2
    }
}

ES6遍历字符串

let of

可以遍历字节大于两位的字符串

padStart

padEnd

可以用来在1前后加零


Array.from([1,3,5],function(item){return item*2});

function(item){return item*2} 相当于map映射

includes对比find和findIndex对NaN处理不会报错

并且能找NaN

[1,2,NaN].includes(NaN) ===> true

{
    let x='test';
    function test2(x,y=x){
        console.log('作用域',x,y);
        //  kill kill
    }
    test2('kill');
}

es6尾调用:函数的最后是不是一个函数

function tail(x){
    console.log('tail',x);
}
function fx(x){
    return tail(x)
}
fx(123)

嵌套函数,依赖函数使用尾调用


es6属性表达式

key值因为另一个变量而变化

{
    let a='b';
    let es5_obj={
        a:'c',
        b:'c'
    };

    let es6_obj={
        [a]:'c'
    }

    console.log(es5_obj,es6_obj);
}

es对象

Object.assign()属于浅拷贝

只拷贝自身对象的属性

不拷贝继承的属性和对象中不可枚举的属性

es Symbol用法

{
    let a1=Symbol.for('abc');
    let obj={
        [a1]:'123',
        'abc':345,
        'c':456
    }
}

但for ..in..和let …of…拿不到Symbol值的

要用

Object.getOwnPropertySymbols(obj).forEach(function(item){
    console.log(obj[item]);
})

两边都取到

Reflect.ownKeys(obj).forEach(function(item){
    console.log('ownkeys',item,obj[item]);
})

ES6Map

Map是对Object的补充,key值可以是任意类型

ES6Set

去重效果

let arr=[1,2,3,1,'2'];
let list2=new Set(arr);

console.log('unique',list2);

但是Set在去重时不会转换数据类型。


一、

weakSet和Set支持的数据类型不一样

weakSet的元素只能是对象

二、

weakSet的对象是弱引用

===》就是在其他地方有没有被引用过,不会跟垃圾回收机制挂钩上

weakSet添加了一个值只是对象的引用,不会整个值拷过来,是不是垃
圾回收掉,不会去检测

三、

不能遍历

es6 Map

{
    let map = new Map();
    let arr=['123'];

    map.set(arr,456);

    console.log('map',map,map.get(arr));
}

{
    let map = new Map([['a',123],['b',456]]);
    console.log('map args',map);
}

数组结构横向对比,增,查,改,删

{
    let map=new Map();
    let array=[];
    // 增
    map.set('t',1);
    array.push({t:1});

    console.info('map-array',map.array);

    // 查
    let map_exist=map.has('t');
    let array_ezist=array.find(item=>item.t);
    console.info('map-array',map_exist,array_exist);

    //改
    map.set('t',2);
    array.forEach(item=>item.t?item.t=2:'');
    console.info('map-array-modify',map,array);

    //删
    map.delete('t');
    let index = array.findIndex(item=>item.t);
    array.splice(index,1);
}

Set和array的对比

{
    let set = new Set();
    let array=[];

    // 增
    set.add({t:1});
    array.push({t:1});

    console.log('set-array',set,array);

    // 查
    let set_exist=set.has({t:1}); 这里的{t:1}与增加时的不一样
    array同上

    // 改
    set.forEach(item=>item.t?item.t=2:'');
    array.forEach(item=>item.t?item.t=2:'');

    // 删
    set.forEach(item=>item.t?set.delete(item):'');
    array同上
}

map,set,object对比

{
    let item={t:1};
    let map = new Map();
    let set = new Set();
    let obj = {};

    // 增
    map.set('t',1);
    set.add(item);
    obj['t']=1;

    console.info('map-set-obj',obj,map,set);

    //查

    console.log({
        map_exist:map.has('t'),
        set_exist:set.has(item),
        obj_exist: 't' in obj
    })

    // 改
    map.set('t',2);
    item.t=2;
    obj['t']=2;

    //删除
    map.delete('t');
    set.delete(item);
    delete obj['t'];

}

Proxy可以认为是代理或拦截

{
    let obj={
        time:'2017-03-11';
        name:'net',
        _r:123
    };

    let monitor=new Proxy(obj,{
        // 拦截对象属性的读取
        get(target,key){
            return target[key].replace('2017','2018')
        }
        // 拦截对象设置属性
        set(target,key,value){
            if(key==='name'){
                return target[key]=value;
            } else {
                return target[key];
            }
        }
        // 拦截key in object操作
        has(target,key){
            if(key==='name'){
                return target[key]
            } else {
                return false;
            }
        }
        // 拦截delete
        deleteProperty(target,key){
            if(key.indexOf('_')>-1){
                delete target[key];
                return true;
            }else {
                return target[key]
            }
        }
        // 拦截Object.keys,Object.getOwnPropertySymbols,
        Object.getOwnPropertyNames

        ownKeys(target){
            return Object.keys(target).filter
            (item=>item!='time')
        }
    });

    console.log('get',monitor.time); // 2018

    monitor.time='2018';
    monitor.name='mukewang';
    console.log('set',monitor.time,mointor);
    // set 2018-03-11
       Proxy{time: "2017-03-11", name: "mukewang", _r: 123}

    console.log('has', 'name' in monitor,'time' in 
    monitor);
    // has true false

    delete monitor.time;
    console.log('delete',monitor);
    // delete
       Proxy{time: "2017-03-11", name: "mukewang", _r: 123}

    delete monitor._r;
    console.log('delete',monitor);
    // delete
       Proxy{time: "2017-03-11", name: "mukewang"}

    console.log('ownKeys',Object.keys(monitor));
    // ownKeys["name","_r"]

}

Reflect用途

obj同上
Reflect.get(obj,'time');

Reflect.set(obj,'name','mukewang');

Reflect.has(obj,'name');

Proxy和Reflect一起的实例用途

{
    function validator(target,validator){
        return new Proxy(target,{
            _validator:validator,
            set(target,key,value,proxy){
                if(target.hasOwnProperty(key)){
                    let va=this._validator[key];
                    if(!!va(value)){
                        return Reflect.set
                        (target,key,value,proxy)
                    }else{
                        throw Error(`不能设置${key}到
                        ${value}`)
                    }
                }else{
                    throw Error(`${key} 不存在`)
                }
            }
        })
    }

    const personValidators={
        name(val){
            return typeof val==='string'
        },
        age(val){
            return typeof val==='number' && val>18
        }
    }

    class Person{
        constructor(name,age){
            this.name=name;
            this.age=age;
            return validator(this,personValidators)
        }
    }

    const person=new Person('lilei',30);

    console.log(person);
    // Proxy {name: "lilei", age: 30}

    person.name=48;
    // 报错 不能设置name到48
}

// 应用==》校验可以加在personValidators中


在类的继承中如果用super传递参数super函数放在函数的第一行

静态方法通过类去调用而不是通过类的实例去调用


{
    let ajax=function(callback){
        相当于执行完ajax执行callback
        即callback相当于回调
    };
}

{
    // 基本定义
    let ajax = function(callback) {
        console.log('执行');
        setTimeout(function() {
            callback && callback.call()
        }, 1000);
    };
    ajax(function() {
        console.log('timeout1');
    })
}

iterator在数组中的应用

{
  let arr=['hello','world'];
  let map=arr[Symbol.iterator]();
  console.log(map.next());
  console.log(map.next());
  console.log(map.next());
}

{value: "hello", done: false}
{value: "world", done: false}
{value: undefined, done: true}

Object没有iterator接口,因为它的数据是我们填充的,不知道里面的数据需要怎么遍历

{
    let obj = {
        start: [1, 3, 2],
        end: [7, 9, 8],
        [Symbol.iterator]() {
            let self = this;
            let index = 0;
            let arr = self.start.concat(self.end);
            let len = arr.length;
            return {
                next() {
                    if (index < len) {
                        return {
                            value: arr[index++],
                            done: false
                        }
                    } else {
                        return {
                            value: arr[index++],
                            done: true
                        }
                    }
                }
            }
        }
    }
    for (const key of obj) {
        console.log(key);
        // 1 3 4  7 9 8
    }
}

注意一、

不管什么样的数据结构,可能简单或复杂
自定义部署要按照以上步骤

要返回next()方法

Generator函数和iterator接口的关系

任意一个对象或接口都是部署在Symbol.iterator属性上的

generator就是一个遍历器生成函数

状态机

{
    let state = function*() {
        while (1) {
            yield 'A';
            yield 'B';
            yield 'C';
        }
    }
    let status = state();
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());    
    // 循环打印
}

async和await是generator的语法糖

{
    let state = async function() {
        while (1) {
            await 'A';
            await 'B';
            await 'C';
        }
    }
    let status = state();
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
}

实例抽奖

{
    let draw = function(count) {
        // 具体抽奖逻辑
        console.log(`剩余${count}次`)
    }

    let residue = function*(count) {
        while (count > 0) {
            count--;
            yield draw(count);
        }
    }

    let star = residue(5);
    let btn = document.createElement('button');
    btn.id = 'start';
    btn.textContent = '抽奖';
    document.body.appendChild(btn);
    document.getElementById('start').addEventListener
    ('click', function() {
        star.next();
    }, false)
}

// 关于长轮询(服务端的某一个状态不断变化,需要定时取状态,因为HTTP是无状态的连接)

怎么取到状态一个是长轮询,另一个是websocket但websocket浏览器兼容性不好

长轮询就是通过定时器不断的访问一个接口

{
    // 长轮询
    let ajax = function*() {
        yield new Promise(function(resolve, reject) {
            // 模拟http请求
            setTimeout(function() {
                resolve({ code: 0 })
            }, 200)
        })
    }

    let pull = function() {
        let generator = ajax();
        let step = generator.next();
        step.value.then(function(d) {
            if (d.code != 0) {
                setTimeout(function() {
                    console.log('wait');
                    pull()
                }, 1000);
            } else {
                console.log(d);
            }
        })
    }

    pull();
}

修饰器三点

  1. 修饰器是一个函数
  2. 修改行为
  3. 修改类的行为

实例-广告插点

{
    let log = (type) => {
        return function(target, name, descriptor) {
            let src_method = descriptor.value;
            descriptor.value = (...arg) => {
                src_method.apply(target, arg);
                console.log(`log ${type}`);
            }
        }
    }

    class AD {
        @log('show')
        show() {
            console.log('ad is show');
        }
        @log('click')
        click() {
            console.log('ad is click');
        }
    }

    let ad = new AD();
    ad.show();
    ad.click();
}

箭头函数的this指向是定义时的指向,而不是运行时的指向

闭包是函数和声明该函数的词法环境的组合。
这个环境包含了这个闭包创建时所能访问的所有局部变量。


hasOwnProperty 是 JavaScript 中处理属性并且不会遍历原型链的方法之一。(另一种方法: Object.keys())

注意:检查属性是否undefined还不够。该属性可能存在,但其值恰好设置为undefined。


当你执行:

var o = new Foo();

JavaScript实际上执行的是:

var o = new Object();
o._proto_ = Foo.prototype;
Foo.call(o);

当你执行:

o.someProp;

===>

Object.getPrototypeOf(o).someProp
Object.getPrototypeOf(Object.getPrototypeOf(o)).someprop

call()方法调用一个函数,其具有一个指定的this值和分别地提供的参数(参数的列表)

返回值是你调用的方法的返回值,若该方法没有返回值,则返回undefined。


§401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。

§403 Forbidden - [*] 表示用户得到授权(与 401 错误相对),但是访问是被
禁止的。


使用es6注意事项

使用严格模式,注意作用域

使用类与对象,结合模块化构建中大型项目

使用Promise替换传统的回调函数

使用箭头函数要注意this的指向

学会使用Generator完成异步操作应用