关于

237 阅读5分钟

防抖

let debounce = (fn,wait)=>{
    let timer = 0;
    return (...args)=>{
        if(timer)clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(this,args)
        },wait)
    }
}

节流

const throttle = (fn, wait) => {
    let finished = true;
    return (...args) => {
        if(!finished)return;
        finished = false;
        setTimeout(() => {
            fn.apply(this, args);
            finished = true;
        }, wait);
    };
};

深拷贝

// 思路:拷贝的数据类型分为:基本数据类型、
const deepClone = (target, map = new Map()) => {
    // 首先处理基本数据类型
    if((typeof target !== 'object' ||  target !== 'function') || target !== null) return target;
    // 判断具体的引用数据类型
    let type = Object.prototype.toString.call(target);
    let cloneTarget;

}

ES6新增的东西

一些细微的拓展

letconstvar 存在变量提升和会绑定到全局window对象

解构赋值 :数组结构和对象结构

箭头函数 特点:形参只有一个可以省略小括号、函数体只有一句话,可以省略大括号,写在一行、不用写return、没有 argumentsthis为外部作用域的this、不能作为构造函数

// 扩展运算符

对象拓展

keys(obj):获取对象的所有key形成的数组
values(obj):获取对象的所有value形成的数组
entries(obj):获取对象的所有key和value形成的二维数组。格式:[[k1,v1],[k2,v2],...]

数组的拓展

find()
返回找出第一个符合条件的数组成员,否则返回undefined。
[1, 4, -5, 10].find((n) => n < 0)  -5

findIndex()
返回找到第一个符合条件的数组成员索引值,不存在则返回-1。
[1, 5, 10, 15].findIndex((value)=>  value > 9) 2

Array.from()
把伪数组转成数组
let arr = Array.from({0: 'a', 1: 'b', 2: 'c', length: 3});// ['a', 'b', 'c']

includes()方法
判断数组是否包含某个值
[1, 4, 3, 9].includes(4, 2);// false, 从2的位置开始查,所以没有找到4

数组实例的 flat(),flatMap()
[1, [2, [3]]].flat(Infinity) // [1, 2, 3]

flatMap()方法对原数组的每个成员执行一个函数,然后对返回值组成的数组执行flat()方法。
// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2]) // [2, 4, 3, 6, 4, 8]

字符串拓展

字符串的includes(), startsWith(), endsWith(),repeat()
includes(str, [position]) 返回布尔值,表示是否找到了参数字符串
startsWidth(str, [position]) 返回布尔值,表示参数字符串是否在原字符串的头部或指定位置
endsWith(str, [position]) 返回布尔值,表示参数字符串是否在原字符串的尾部或指定位置。
console.log('hello world'.includes('e', 2)); // false 从位置2开始查找e,没有找到
console.log('hello world'.includes('e')); // true
console.log('hello world'.startsWith('h')); // 未指定位置,看开头是否是h,返回true
console.log('hello world'.startsWith('l', 2)); // 指定位置的字符是l,返回true
console.log('hello world'.endsWith('d')); // 未指定位置,结尾是d,返回true
console.log('hello world'.endsWith('r', 9)); // 指定位置的字符是r,返回true

let html = '<li>itheima</li>';
html = html.repeat(10);

闭包实现模块化

实现链式操作

函数想要实现链式调用就必须返回一个实例,比如说数组map之后可以继续调用...

//创建一个类
class Person{
  setName(){
    this.name = name;
    return this;
  }
  setAge(){
    this.age = age;
    return this;
  }
};
//实例化
var person= new Person();
person.setName("Mary").setAge(20);

链式操作的缺点:比如说我原型上的某个方法想返回某个值,就不能再链式调用下去,或者只能放到最后去调用。

链式操作的有点:可以使得异步编程的流程更加清晰,不会像回调函数一样相互耦合,
jQuery和ES6中的Promise也正是沿用了这一思想,Promise每一个异步任务返回一个Promise对象,
通过then方法指定回调函数。

属性的.和[]

this.xxxthis['xxx' + a] 是一样的

一开始JS引擎只有this['xxx'],现在写this.xxx其实JS引擎也会内部转成this['xxx']

常见的运算符

算术运算符

加减乘除取余、自增、自减

赋值运算符

=、+=、-=、*=、/=、%=、按位与赋值(&=)、按位或赋值(|=)、按位非赋值(~=)、

位运算符

按位与(&)、按位或(|)、按位非(~)、按位异或(^)、<<左移、>>右移、>>>有符号右移

二进制:512 256 64 32 | 16 8 4 2 1(左右手)
负数:将正数10互换再加上1   -9 =>1001=>0110+1=> 1111 1111 1111 1111 1111 1111 1111 0111

按位非(NOT)
~25 => -(25)-1  => -26
~~25 => -(25)-1  => -26 => -(-26)-1 => 25

按位与(AND)
25 & 3 => 11001 & 00011 => 找同时存在1的位数,才取1 => 00001 => 1

按位或(OR)
25 | 3 => 11001 & 00011 => 找存在1的位数,就取1 => 11011 => 27

按位异或(XOR)
25 ^ 3 => 11001 & 00011 => 找存在1的位数,就取1,同时存在,则不取 => 11010 => 26
var a=10,b=9; a ^= b, b ^= a, a ^= b; //a=9,b=10


<<左移
-2<<5 => 2的二进制为10,全部向做移5位 => 0000010-> 1000000 => -64

>>右移
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃
-9 >> 2 => 1001 -> 10 => -2

>>>有符号右移
正数>>>和>>结果一样,负数>>>数值会很大

取整:
~~3.9 => 3
3.9 | 0 => 3
3.9 ^ 0 => 3
3.9 << 0 => 3

逗号运算符(,)

能够先执行运算符左侧的操作数,然后再执行右侧的操作数,最后返回右侧操作数的值。
a = (b = 1,c = 2);  //连续执行和赋值
console.log(a);  //返回2
console.log(b);  //返回1
console.log(c);  //返回2

需要注意的关键字

in

除了配合for遍历对象,还可以判断某个属性是否属于某个对象(包括原型链上的原型)
如:
"make" in {make: "Honda", model: "Accord", year: 1998}  // returns true
0 in ["redwood", "bay", "cedar", "oak", "maple"]        // returns true
"length" in trees // returns true (length is an Array property)

instanceof

一个对象能否通过原型链找到另一个对象的原型

Class 与 Style 如何动态绑定?

Class

对象语法:

<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>

data: {
  isActive: true,
  hasError: false
}
复制代码
数组语法:

<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>

data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

style

对象语法:

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

data: {
  activeColor: 'red',
  fontSize: 30
}

数组语法:

<div v-bind:style="[styleColor, styleSize]"></div>

data: {
  styleColor: {
     color: 'red'
   },
  styleSize:{
     fontSize:'23px'
  }
}

JavaScript 语句标识

for - 按条件循环代码块一定的次数
let i = 0;
for(;i<10;){
    i++
}
while - 按条件循环代码块一定的次数
let j = 0;
while(j<10){
    i++
}
forin  - 用于遍历对象的属性
dowhile - 先执行一个语句块,再按条件循环代码块一定的次数

var text = ""
var i = 0;
do {
    i++;
} while (i < 5);

打印100以内的质数

//只能被1和自己整除的数
let arr = [];
for(let i = 2,count = 0; i<100; i++){ //首先1肯定不是,100也不是
    for(let j = 1; j<=i; j++)if(i%j==0)count++;//拿到一个数和之前的数取余,如果取余为0,次数count累加
    if(count === 2)arr.push(i);//如果取余次数只有两次(只能被1和自己整除的数),则为质数
    count = 0;//重置次数
}

斐波那契数列

function Fibonacci(n){
    let arr = []
    let n1 = 1, n2 = 1;
    arr.push(n1,n2)
    for (let i = 2; i < n; i++){
        [n1, n2] = [n2, n1 + n2];
        arr.push(n2)
    }
    return arr;
}
Fibonacci(10)


function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
  if( n <= 1 ) {return ac2};
  return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}

caller和arguments.callee和fn.length

arguments为实参集合,是个类数组,里面有个属性是callee,是函数本身,常用于
一个匿名函数内部想要得到匿名函数本身

function fn(){
    console.log(arguments.callee === fn)//true
    console.log(arguments.callee.length)//0 形参长度
    console.log(arguments.length)//3 实参长度
}
fn(1,2,3)




function f1(){
    f2()
}
function f2(){
    console.log(f2.caller)//f1(){} 指向谁在调用它的函数
}
f1()

严格模式下caller、callee、arguments都不可以被通过

JSON.stringify()和toString()的区别

  1. toString()是转化成字符串,因此不带 [ ]
  2. JSON.stringify是转成JSON字符串,是带[]的

迭代

  1. JavaScript内置的可迭代对象有:String、Array、Map、Set
  2. 当迭代这些数据类型的时候(比如说for...of),JavaScript内部就会(不带参数)调用这些数据类型原型上@@iterator方法(可通过常量 Symbol.iterator 访问该属性),然后返回一个符合迭代器协议的对象,再通过迭代器去获得要迭代的值。
  3. 一些内置的语法结构——比如for...of循环、展开语法、yield*,和解构赋值——其内部实现也使用了同样的迭代协议:
[...someString]                              // ["h", "i"]
[][Symbol.iterator]() + '' //"[object Array Iterator]"
''[Symbol.iterator]() + '' //"[object String Iterator]"
new Map()[Symbol.iterator]() + '' //"[object Map Iterator]"
new Set()[Symbol.iterator]() + '' //"[object Set Iterator]"

let iterator1 = [][Symbol.iterator]();  //返回一个迭代器
let iterator2 = ''[Symbol.iterator]();  //返回一个迭代器
let iterator3 = new Map()[Symbol.iterator]();  //返回一个迭代器
let iterator4 = new Set()[Symbol.iterator]();  //返回一个迭代器

iterator1.next();    // { value: xxx, done: false }
iterator1.next();    // { value: xxx, done: false }
...

使object对象变成可迭代的对象:

也就是说Object上没有@@iterator这个方法,所以object对象不是可迭代,但是我们可以给Object原型上自定义一个[Symbol.iterator]的方法,使object对象变成可迭代的对象。

没有给对象自定义可迭代方法时:

var myIterable = {};
for( key of myIterable){
    console.log(key)
}
//Uncaught TypeError: myIterable is not iterable

给对象自定义可迭代方法时:

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
for( key of myIterable){
    console.log(key)
}
//1
//2
//3

也就是说我们可以改变可迭代对象的方法或者讲任一一个对象变为可迭代。

使一个新创建出来的类实例变成可迭代的对象:

没有给类实例自定义可迭代方法时:

class SimpleClass {
  constructor(data) {
    this.data = data
  }
}
const simple = new SimpleClass([1,2,3,4,5])
for (const val of simple) {
  console.log(val)
}
//Uncaught TypeError: simple is not iterable

给类实例自定义可迭代方法时:

class SimpleClass {
  constructor(data) {
    this.data = data
  }
  [Symbol.iterator]() {
    return {
      next: () => {
        if (index < this.data.length) {
          return {value: this.data[index++], done: false}
        } else {
          return {done: true}
        }
      }
    }
  }
}

const simple = new SimpleClass([1,2,3,4,5])

for (const val of simple) {
  console.log(val)   //'1' '2' '3' '4' '5'
}

简单迭代器

function makeIterator(array) {
    let nextIndex = 0;
    return {
       next: function () {
           return nextIndex < array.length ? {
               value: array[nextIndex++],
               done: false
           } : {
               done: true
           };
       }
    };
}

let it = makeIterator(['哟', '呀']);

console.log(it.next().value); // '哟'
console.log(it.next().value); // '呀'
console.log(it.next().done);  // true