JavaScript笔记

输入和输出

浏览器弹出警示框:alert(‘ ’)
浏览器弹出输入框,用户可以输:prompt(‘ 提示信息’)
控制台打印输出:console.log(‘名’)

变量

声明变量并赋值

var age(起一个变量名) = 18(变量里的值)

交换变量值

声明一个变量3,变量3=变量1,变量1=变量2,变量2=变量3, =会把后面的值给前面 而不是前面的值给后面

数据类型

简单数据类型

数字型:Number
1.整型值(整数) 比如:20
2.浮点型值 (小数)比如: 0.2
3.八进制,十六进制               
4.infinity   infinity无穷大,-infinity无穷小,
5.NaN   非数值
字符串型:String
使用单双引号表示字符串 "a" 'a'
布尔值型:Boolean
truefalse
true    *表示对,与数字型相加时等价于1
false    *表示错,与数字型相加时等价于0
Undefined *只声明未赋值
Null *值为空 与数字型相加时 null=0

复杂数据类型

对象 Object
数组 Array

字符串转义符

换行符:‘\n’
斜杠:‘\’
缩进:‘\t’
空格:‘\b’

字符串长度

length
var strMsg = "我是帅气多金的程序猿!";      
log(strMsg.length)   // 可以拿到字符串有多少个字符

数字保留小数

.toFixed(2) 保留两位小数

括号写几就保留几

判断数字是否为整数

Number.isInteger( )
console.log(Number.isInteger(10)); // true

字符串拼接

1.多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
2. `` 用这个反引号包裹

检测数据类型

typeof( ) 用于检测简单数据类型
var num = 18;
console.log(typeof(num)) // 结果 number数字型
isNaN( ) 检测是否为非数字
如果是非数字 则返回true, 如果不是非数字 则返回false

数据类型转换

转为字符串型
1. 变量.toString() 
2. String(变量)
3. 加+号进行拼接:数据 + ""
转为数字型
1. parseInt('字符串数字') 将字符串型转为整数数值型
2. parseFloat('字符串数字') 将字符串型转为浮点数数值型
3. Number('字符串数字')  将字符串型转为数值型  *强制转换
4. ('字符串数字'-0) 隐式转换 利用算术运算转换为数值型 - * / 都可
转为布尔型
Boolean( 值 )

1. 代表空、否定的值会被转换为 false  ,如 ''、0、NaN、null、undefined     *如果这些带引号,就代表是字符串 就会转为 true
2. 其余值都会被转换为 true

关键字和保留字 标识符

1 标识符

标识(zhi)符:就是指开发人员为变量、属性、函数、参数取的名字。

标识符不能是关键字或保留字。

2 关键字

关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。

包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。

3 保留字

保留字:实际上就是预留的“关键字”,意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。

包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。

注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。

命名规范

变量的名称一般用名词

函数的名称一般用动词

运算符优先级

  1. 小括号()
  2. 一元运算符 ++ – !
  3. 算数运算符 先* / % 后= -
  4. 关系运算符 > >= < <=
  5. 相等运算符 == != === !==
  6. 逻辑运算符 先&&后||
  7. 赋值运算符 =
  8. 逗号运算符 ,

判断语句(流程控制)

三元表达式

表达式1 ? 表达式2 : 表达式3;     

如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值

if语句

if (条件表达式) {
    // 条件成立执行的代码语句
}

if 语句(双分支语句)

if (条件表达式) {
    // [如果] 条件成立执行的代码
} else {
    // [否则] 执行的代码
}

if 语句(多分支语句)

if (条件表达式1) {
    语句1} else if (条件表达式2)  {
    语句2} else if (条件表达式3)  {
   语句3....
} else {
    // 上述条件都不成立执行此处代码
}

switch 语句

switch( 表达式 ){ 
    case value1:
        // 表达式 等于 value1 时要执行的代码
        break;
    case value2:
        // 表达式 等于 value2 时要执行的代码
        break;
    default:
        // 表达式 不等于任何一个 value 时要执行的代码
}

循环

for循环

for(初始化变量; 条件表达式; 操作表达式 ){
    //循环体
}

for 循环重复相同的代码

// 用户输入次数
var num = prompt('请输入次数')for ( var i = 1 ; i <= num; i++) {
    console.log('媳妇我错了~');
} 

for 循环重复不相同的代码

// for 里面是可以添加其他语句的 
for (var i = 1; i <= 100; i++) {
 if (i == 1) {
    console.log('这个人今年1岁了, 它出生了');
 } else if (i == 100) {
    console.log('这个人今年100岁了,它死了');
  } else {
      console.log('这个人今年' + i + '岁了');
  }
}

双重for循环

for (外循环的初始; 外循环的条件; 外循环的操作表达式) {
    for (内循环的初始; 内循环的条件; 内循环的操作表达式) {  
       需执行的代码;
   }
}

while循环

while (条件表达式) {
    // 循环体代码 
}

do-while循环

do {
    // 会先执行一次循环体代码 - 条件表达式为 true 时再重复执行循环体代码
} while(条件表达式);

循环中的关键字

continue 跳出本次循环
for (var i = 1; i <= 5; i++) {
     if (i == 3) {
         console.log('这个包子有虫子,扔掉');
         continue; // 跳出本次循环,跳出的是第3次循环 
      }
      console.log('我正在吃第' + i + '个包子呢');
 }
break 退出整个循环
for (var i = 1; i <= 5; i++) {
   if (i == 3) {
       break; // 直接退出整个for 循环,跳到整个for下面的语句
   }
   console.log('我正在吃第' + i + '个包子呢');
 }

数组

利用 new 创建数组
var 数组名 = new Array()var arr = new Array();   // 创建一个新的空数组
利用数组字面量创建数组
//1. 使用数组字面量方式创建空的数组
var  数组名 = []//2. 使用数组字面量方式创建带初始值的数组
var  数组名 = ['小白','小黑','大黄','瑞奇'];
通过索引 (下标) 获取数组中的元素

用来访问数组元素的序号(数组下标从 0 开始)

// 定义数组
var arrStus = [1,2,3];
// 获取数组中的第2个元素
alert(arrStus[1]);   

数组方法

遍历数组的方法

for循环遍历
var arr = ['red','green', 'blue'];
for(var i = 0; i < arr.length; i++){
    console.log(arrStus[i]);
}
for of 遍历
var arr = ['red','green', 'blue'];
for(var k of arr){
    console.log(k);
}
for in 遍历
var arr = ['red', 'green', 'blue'];
for (var k in arr) {
    console.log(arr[k]);
}
forEach 遍历
var arr =[1,2,3,4]
arr.forEach(function(item,index,args){
    // item数组里的每个值
    // index 是索引
    // args 是当前数组
})

筛选数组的方法

filter 过滤数组

返回满足条件的

var arr = [12, 66, 4, 88, 3, 7];
var newArr = arr.filter(function(value, index,array) {
  	 //参数一是:数组元素
     //参数二是:数组元素的索引
     //参数三是:当前的数组
     return value >= 20
});
console.log(newArr);//[66,88] //返回值是一个新数组
includes( ) 数组中是否包含某个元素

返回一个布尔值

var arr1=[1,2]
var res=arr1.includes(3)
console.log(res) // false
// 数组里存在这个值返回 true  否返回false
some 查找数组中是否有满足(符合)条件的元素

返回一个布尔值

 var arr = [10, 30, 4];
 var flag = arr.some(function(value,index,array) {
    //参数一是:数组元素
     //参数二是:数组元素的索引
     //参数三是:当前的数组
     return value < 3;
  });
console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环
every 判断数组中每一个元素是否都满足条件

返回一个布尔值

var arr = [10, 30, 4];
var arr1 = arr.every(function (item, index, ages) {
       return item > 0
})
console.log(arr1); // true  //返回值是布尔值,只有全部满足条件才会返回true
map 将数组中的元素按照需求全部处理一下
 var arr = [1, 2, 3, 4, 5]
 var res = arr.map(function (item, index, args) {
      return item + 1
 })
console.log(res);
 // item 表示数组的每一项
 // index 表示索引
 // args 表示原数组
find() 找出第一个符合条件的数组成员

如果没有找到返回undefined

let ary = [{
     id: 1,
     name: '张三'
 }, { 
     id: 2,
     name: '李四'
 }]; 
 let target = ary.find((item) => item.id == 2);
//找数组里面符合条件的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
findIndex() 找出第一个符合条件的数组成员的索引

如果没有找到返回-1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((item) => item > 9); 
console.log(index); // 2

获取数组中元素索引方法

indexOf 数组中查找目标的第一个索引号

如果目标存在返回索引号,不存在则返回-1

var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.indexOf('blue'));  // 2
lastIndexOf 数组中查找目标的最后一个索引号

如果目标存在返回索引号,不存在则返回-1

var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.lastIndexOf('blue'));  // 4

数组中添加元素

length
数组[ 数组.length ] = 新数据;
push

数组的末尾 添加一个或者多个数组元素 返回值是新数组长度

var arr = [1, 2, 3];
arr.push(4, 5, 6);
console.log(arr.push(4, 5, 6)) // 6  *数组长度
console.log(arr)  // 1 2 3 4 5 6
unshift

数组的开头 添加一个或者多个数组元素 返回值是新数组长度

var arr = [1, 2, 3];
arr.unshift(4 , 5);   * 返回值同上
splice

根据索引插入元素 *会改变原数组

var a=[1,2,3,4,5,6]
a.splice(3,0,10) 
// a=[1,2,3,10,4,5,6]

删除数组中的元素

shift

删除数组的第一个元素 返回值是删除的那个元素

var arr = [1, 2, 3]; 
arr.shift();
console.log(arr.shift()) // 1   *返回值为删除的那个元素
pop

删除数组的最后一个元素 返回值是删除的那个元素

var arr = [1, 2, 3];
arr.pop();     // 3   *返回值为删除的那个元素
splice

根据索引删除数组里的元素 *会改变原数组

var a=[1,2,3,4,5,6]
// 从索引为1的位置开始删除到最后
a.splice(1)    // a=[1]
// 从索引号为3的位置删除到4的位置
a.splice(3,4)  // a=[1,2,3,6]

检测是否为数组

instanceof 运算符

可以判断前者是否属于后者

var arr = [1, 23];
// 判断数组
console.log(arr instanceof Array); // true
Array.isArray()

判断是否为数组

var arr = [1, 23];
console.log(Array.isArray(arr));   // true
constructor
var arr = []
console.log(arr.constructor);
Object.prototype.toString.call
var arr = []
console.log(Object.prototype.toString.call(arr));

合并数组的方法

concat( )
var arr1=[1,2]
var arr2=[3,4]
var arr3=[5,6]
var res=arr1.concat(arr2,arr3)
console.log(res) // [1,2,3,4,5,6]
扩展运算符合并数组
 let ary1 = [1, 2, 3];
 let ary2 = [3, 4, 5];
 // 方法一 
 let ary3 = [...ary1, ...ary2];
 // 方法二 
 ary1.push(...ary2);

扩展运算符(展开语法)

let ary = [1, 2, 3];
 console.log(...ary);    // 1 2 3

伪数组转换为真数组

Array.from()
//定义一个集合
let arrayLike = {
    // 属性名必须是索引号形式
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3  // 必须要有长度
}; 
//转成数组
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

let arrayLike = { 
     "0": 1,
     "1": 2,
     "length": 2
 }
 let newAry = Array.from(arrayLike, item => item *2)//[2,4]
扩展运算符
let oDivs = document.getElementsByTagName('div'); 
oDivs = [...oDivs];

数组排序的方法

reverse 翻转数组

颠倒数组中元素的顺序,该方法会改变原来的数组

var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);
sort 数组排序

对数组的元素进行排序,该方法会改变原来的数组

var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function(a, b) {
       return a - b;   // 升序的顺序排列
       return b - a;   // 降序的顺序排列
});
console.log(arr1);

数组求和的方法

reduce
var arr = [1, 2, 3, 4]
// 0 代表sum 的初始值 相当于var sum=0
var res = arr.reduce((sum, item) => sum += item, 0)
console.log(res); // 10

数组去重的方法

filter + indexOf 数组去重
var arr = [1, 2, 3, 4, 5, 1, 2, 3]
    var arr1 = arr.filter(function (item, index) {
      return arr.indexOf(item) === index
    })
console.log(arr1);
new Set() + … 数组去重
var arr = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
var res = [...new Set(arr)]
Array.from() + new Set() 数组去重
var arr = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
var res = Array.from(new Set(arr))

数组里面的元素都是对象的去重方法

注意:每个对象元素必须都有id
方法 1 用forEach 配合 find
var arr1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, {   id: 5 }, { id: 6 }, { id: 7 }];
var arr2 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, {   id: 5 }];
var arr = []
// 必须循环数据多的那个
arr1.forEach(item => {
	var ret = arr2.find(obj => item.id === obj.id)
	if(!ret) {
	  arr.push(item)
	}
})
方法 2 用filter 配合 find
var arr1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, {   id: 5 }, { id: 6 }, { id: 7 }];
var arr2 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, {   id: 5 }];
// 必须循环数据多的那个   filter返回一个新数组
var arr = arr1.filter(item => {
   // find 返回符合条件的元素 没有符合的就返回undefined  给一个变量来接着
	var ret = arr2.find(obj => item.id === obj.id)
    // 如果有元素返回 则证明 两个数组都有这个数据 取反为false  filter就不返回这个数据
    // 如果find返回的是undefined 则证明 用户频道数组里没有这条数据 undefined取反为true  filter就会返回这个数据
	return !ret
})

--------------------------------------------------------
// 简写
var arr = arr1.filter(item => {
    return !arr2.find(obj => item.id === obj.id)
  })

数组转换为字符串

toString 把数组换成字符串,逗号分隔每一项
var arr = [1, 2, 3];
console.log(arr.toString()); // 1,2,3
join(‘分隔符’)

把数组中的每一个元素转换为一个字符串 用指定分隔符分隔

分隔符:,。¥# 任何符号 * join方法如果不传入参数,则按照逗号拼接元素

var arr1 = ['green', 'blue', 'pink'];
console.log(arr1.join()); // green,blue,pink
console.log(arr1.join('-')); // green-blue-pink
console.log(arr1.join('&')); // green&blue&pink

截取数组

slice()

slice(‘截取的起始位置’, ‘截取到哪个位置’)

不会改变原数组返回一个新数组

var str1 = [改,革,春,风,吹,满,地];
console.log(str1.slice(2,5)); 

对象

访问对象的属性
console.log(star.name)     // 调用名字属性
console.log(star['name'])  // 调用名字属性
调用对象里的方法
var obj = {
    sayHi: function(){
        alert('大家好啊~');
    }
 };
obj.sayHi();  // 调用 sayHi 方法,注意,一定不要忘记带后面的括号
打印对象
console.dir(对象名);
Object.is 比较两个值是否相等
console.log(Object.is(NaN, NaN));    // true
console.log(Object.is(0, -0));     // false
console.log(Object.is(0, 0));    // true

创建对象

使用对象字面量创建对象
var star = {
    name : 'pink',
    age : 18,
    sex : '男',
    sayHi : function(){
        alert('大家好啊~');
    }
};
利用 new Object 创建对象
var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
    alert('大家好啊~');
}
利用构造函数创建对象
function 函数名(形参1,形参2,形参3) {
     this.属性名1 = 参数1;
     this.属性名2 = 参数2;
     this.属性名3 = 参数3;
     this.方法名 = 函数体;
}
var obj = new 函数名(实参1,实参2,实参3)
利用类创建对象
// 1. 创建类 class创建一个类
class Star {
    // 类的共有属性放到 constructor 里面 constructor是 构造器或者构造函数
    constructor(uname, age) {
      this.uname = uname;
      this.age = age;
    }  //------------------------------------------->注意,方法与方法之间不需要添加逗号
    sing(song) {
      console.log(this.uname + '唱' + song);
    }
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 18);
console.log(ldh); // Star {uname: "刘德华", age: 18}
ldh.sing('冰雨'); // 刘德华唱冰雨

对象方法

in 检测某个属性是否属于这个对象
var obj = {
     age: 1
 }
 console.log('age' in obj);

检测是否为对象

instanceof 运算符

判断前者是否属于后者

var obj = {};
console.log(obj instanceof Object); // true

// 判断函数是否也是对象
var f = new Function('a', 'b', 'console.log(a+b)')
f(1, 2)
console.log(f instanceof Object);  // true
constructor
var obj = {}
console.log(obj.constructor);
Object.prototype.toString.call
var obj = {}
console.log(Object.prototype.toString.call(obj));

遍历对象

for in 遍历
for (var k in obj) {
    console.log(k);      // 这里的 k 是属性名
    console.log(obj[k]); // 这里的 obj[k] 是属性值
}
遍历数组里的对象
arr = [{ age: 1 }, { sex: '男' }]
arr.forEach(function (item, index) {
    console.log(item);  // 代表每一格对象
    console.log(item.age);   // 输出对象里的这个属性
    console.log(index);  // 代表每一个对象的索引
})
Object.keys() 遍历对象里的key

返回一个数组,成员参数是对象自身的所有可遍历的属性名

Object.values() 遍历对象里的值

返回一个数组,成员是参数对象自身的所有可遍历的属性值

var person = {
    name: 'rayn',
    age: 18
}
// 遍历对象里的名
var keys = Object.keys(person)
console.log(keys); // [ 'name', 'age' ]
// 遍历对象里的值
var values = Object.values(person)
console.log(values); // [ 'rayn', 18 ]

JSON 和 JS对象的相互转换

JSON.parse() 字符串转对象
JSON.stringify() 对象转字符串
// 字符串转对象
var json = '{"a": "Hello", "b": "world"}'
var obj = JSON.parse(json)
console.log(obj)

// 对象转字符串
var obj2 = { a: 'hello', b: 'world', c: false }
var str = JSON.stringify(obj2)
console.log(str)

对象拷贝

Object.assign (深拷贝)

用于将源对象合并到目标对象

var obj = {
       aa: 1
}
var a = Object.assign({}, obj)
console.log(a);
// 第一个参数是拷贝到   把obj拷贝到{}里 可拷贝多个对象 ,分隔
// Object.assign({}, obj,obj1,obj2)
深拷贝
var obj = {
            id: 1,
            name: 'andy',
            msg: {
                age: 18
            },
            color: ['pink', 'red']
        };
var o = {};
// 深拷贝拷贝多层, 每一级别的数据都会拷贝.
        function deepCopy(newobj, oldobj) {
            for (var k in oldobj) {
                // 判断我们的属性值属于那种数据类型
                // 1. 获取属性值  oldobj[k]
                var item = oldobj[k];
                // 2. 判断这个值是否是数组
                if (item instanceof Array) {
                    newobj[k] = [];
                    deepCopy(newobj[k], item)
                } else if (item instanceof Object) {
                    // 3. 判断这个值是否是对象
                    newobj[k] = {};
                    deepCopy(newobj[k], item)
                } else {
                    // 4. 属于简单数据类型
                    newobj[k] = item;
            }

     }
}
deepCopy(o, obj);
console.log(o);

添加或修改对象中的属性

Object.defineProperty
Object.defineProperty(对象,修改或新增的属性名,{
    value: 修改或新增的属性的值,
	writable: true/false,//如果值为false 不允许修改这个属性值
	enumerable: false,//enumerable 如果值为false 则不允许遍历
    configurable: false  //configurable 如果为false 则不允许删除这个属性 属性是否可以被删除或是否可以再次修改特性
})	
简单写法
var obj = {
    id: 1,
    pname: '小米',
    price: 1999
 };
obj.num = 1000;
obj.price = 99;
console.log(obj);

函数

函数的声明方式

声明式(命名函数)
function fn() {...}
// 调用  
fn();  
函数表达式方式(匿名函数)
// 这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(){...};
// 调用的方式,函数调用必须写到函数体下面
fn();
利用 new Function(‘参数1’,‘参数2’, ‘函数体’);
var f = new Function('a', 'b', 'console.log(a + b)');

f(1, 2);

函数的调用方式

直接调用函数
函数名();  // 通过调用函数名来执行函数体代码

函数的封装

计算1-100之间值的函数

// 声明函数
function getSum(){
  var sumNum = 0;// 准备一个变量,保存数字和
  for (var i = 1; i <= 100; i++) {
    sumNum += i;// 把每个数值 都累加 到变量中
  }
  alert(sumNum);
}
// 调用函数
getSum();

函数的参数

// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
  // 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...); 

函数的返回值

return 语句

return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码

// 声明函数
function 函数名(){
    ...
    return  需要返回的值;
}
// 调用函数
函数名();    
console.log(函数名()) // 此时打印函数就可以得到函数体内return的值

函数中 arguments的使用

当不确定有多少个参数传递的时候,可以用 arguments 来获取。JavaScript 中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。arguments展示形式是一个伪数组,因此可以进行遍历

 function fn() {
    console.log(arguments);
}
fn()

内置对象MDN

Math 对象 (数学对象)

Math.PI 圆周率
Math.floor() 向下取整
Math.floor()   // 向下取整  往最小了取值
console.log(Math.floor(1.1)); // 1
console.log(Math.floor(1.9)); // 1
Math.ceil() 向上取整
Math.ceil()   //ceil 天花板 向上取整  往最大了取值
console.log(Math.ceil(1.1)); // 2
console.log(Math.ceil(1.9)); // 2
Math.round() 四舍五入版 就近取整
Math.round()   //四舍五入  其他数字都是四舍五入,但是 .5 特殊它往大了取  
console.log(Math.round(1.1)); // 1
console.log(Math.round(1.5)); // 2
console.log(Math.round(1.9)); // 2
console.log(Math.round(-1.1)); // -1
console.log(Math.round(-1.5)); // 这个结果是 -1
Math.abs() 绝对值
console.log(Math.abs(1)); // 1
console.log(Math.abs(-5)); // 5
console.log(Math.abs('-5')); // 隐式转换 会把字符串型 -5 转换为数字型
console.log(Math.abs('pink')); // NaN 
Math.max() / Math.min() 求最大和最小值
console.log(Math.max(6,5,4,9,2,7,)); 
Math.random() 随机数
function getRandom() {
     return Math.floor(Math.random() * 100 );
}
console.log(getRandom());  //0-100 之间的随机数但不包含100 
取多少进制的随机数
toString(16) // 16进制
substr(2)   // 去掉前面的0.
var x = Math.random().toString(16).substr(2)
console.log(x);

Date 日期对象

获取当前时间
var now = new Date();
 console.log(now);
获取指定时间的日期对象
var future = new Date('2019/5/1');
getFullYear() 获取当年
 var date = new Date();
  console.log(date.getFullYear()); 
 // 返回当前日期的年 
getMonth() 获取当月
var date = new Date();
console.log(date.getMonth() + 1);                 
 // 月份 返回的月份小1个月   记得月份+1 呦
getDate() 获取当日
var date = new Date();
console.log(date.getDate()); // 返回的是 几号
getDay() 获取今天星期几
var date = new Date();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay(); // 得出的数字正好能对应索引
 console.log(arr[day])
getHours() 获取当前小时
 var time = new Date();
 console.log(time.getHours();)
getMinutes() 获取当前分钟
var time = new Date();
console.log(time.getMinutes();)
getSeconds() 获取当前秒
var time = new Date();
console.log(time.getSeconds();)
valueOf() 获取当前毫秒
getTime() 获取当前毫秒
var date = new Date();
console.log(date.valueOf());
console.log(date.getTime());
获取当前毫秒 简单写法
var date = +new Date()

string 字符串对象

查找字符的位置(索引)
indexOf(‘要查找的字符’,开始的位置)
var str = 'andy';
console.log(str.indexOf('n',0)); // 1
根据索引返回字符
charAt( )
var str = 'andy';
console.log(str.charAt(3)); // y
截取字符
substr()

substr(‘截取的起始位置’, ‘截取几个字符’) 返回一个新的

var str1 = '改革春风吹满地';
console.log(str1.substr(2, 2)); // 第一个2 是索引号的2 从第几个开始  第二个2 是取几个字符  返回一个新的
slice()

slice(‘截取的起始位置’, ‘截取到哪个位置’) 返回一个新的

 var str1 = '改革春风吹满地';
console.log(str1.slice(2, 3))
替换字符
replace

replace(‘被替换的字符’, ‘替换为的字符’) 它只会替换第一个字符

 var str = 'andyandy';
 console.log(str.replace('a', 'b'));  // bndyandy
替换全部字符 /正则表达式写法

g 全局匹配

i 忽略大小写

gi 可连写

var str = 'andyandy'; 
console.log(str.replace(/a/g, 'b'));  // bndybndy
字符串转为数组
split(‘分隔符’)
var params = 'red=pink=blue';
var arr = params.split('=')
console.log(arr);
// 就是将字符串变为数组 并且把=号 变为逗号,

String 的扩展方法

模板字符串

模板字符串中可以解析变量

模板字符串中可以换行

在模板字符串中可以调用函数

实例方法:startsWith() 和 endsWith()

  • startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
  • endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello world!';
str.startsWith('Hello') // true 
str.endsWith('!')       // true

实例方法:repeat()

repeat方法表示将原字符串重复n次,返回一个新字符串
'x'.repeat(3)      // "xxx" 
'hello'.repeat(2)  // "hellohello"

字母小写转为大写

toUpperCase()
var a = 'a'
console.log(a.toUpperCase()); // A

ES6 新增数据结构

Set 数据结构

结构类似于数组,但是成员的值都是唯一的,没有重复的,

初始化 set 结构
var s = new Set([1,1,2,2,3,3])
console.log(s);   // 1,2,3
size

Set 结构也和数组一样具备 长度属性, 但是Set 结构中是 size

var s = new Set([1, 1, 2, 2, 3, 3, 3, 4, 5, 6])
console.log(s);   // 1,2,3,4,5,6
console.log(s.size);  //  6
利用Set进行数组去重
var arr = Array.from(new Set([1, 1, 2, 2, 3, 3, 3, 4, 5, 6]))
console.log(arr);  // [1,2,3,4,5,6]
add 方法用于给 set 结构增加数据

可连续调用,返回 Set 结构本身

var s = new Set([1,1,2,2,3,3])
s.add(4).add(5).add(6) 
console.log(s);   // 1,2,3,4,5,6
delete 方法用于删除某个值
var s = new Set([1, 1, 2, 2, 3, 3])
var flag = s.delete(2)
console.log(s, flag);  // 1,3
clear 方法用于清除所有成员,没有返回值
var s = new Set([1,1,2,2,3,3])
s.clear()
console.log(s);  // 空Set[]
has 方法用于判断 当前set 结构是否有某些数据
var s = new Set([1, 1, 2, 2, 3, 3])
console.log(s.has(2));  // true
console.log(s.has(22));   // false

Map 结构

js 对象本质就是一个键值对的集合,但是只能用字符串作为键 map 结构类似于对象,也是一个键值对的集合,但是键可以是任何数据

set 方法用于向 Map 结构中增加数据
var m = new Map()
var obj = {a: 1}
m.set(obj, 'test')
console.log(m);// Map(1) { { a: 1 } => 'test' }
get 方法用于向 Map 结构中获取数据
var m = new Map()
var obj = { a: 1 }
m.set(obj, 'test')
console.log(m.get(obj));   // test
delete 方法用于删除 Map 结构中指定的数据
var m = new Map()
var obj = {a: 1}
m.set(obj, 'test')
m.delete(obj)
console.log(m);
has 方法用于判断 Map 结构中是否存在指定数据
var m = new Map()
var obj = {a: 1}
m.set(obj, 'test')
console.log(m.has(obj));    // true
clera 方法用于清除所有成员
var m = new Map()
var obj = {a: 1}
var obj2 = {a: 2}
m.set(obj, 'test').set(obj2, 'test2')
m.clear()
console.log(m);  // 空Map{}

面向过程与面向对象

面向过程

  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。

面向对象

  • 面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。

面向过程与面向对象对比

面向过程面向对象
优点性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点不易维护、不易复用、不易扩展性能比面向过程低

在 ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个,通过类实例化一个具体的对象

创建类
// 1. 创建类 class  创建一个 明星类
 class Star {
   // 类的共有属性放到 constructor 里面
   constructor(name, age) {
     this.name = name;
     this.age = age;
   }
 }
   // 2. 利用类创建对象 new
   var ldh = new Star('刘德华', 18);
   console.log(ldh); 
类添加属性
 // 1. 创建类 class  创建一个类
class Star {
    // 类的共有属性放到 constructor 里面 constructor是 构造器或者构造函数
    constructor(uname, age) {
      this.uname = uname;
      this.age = age;
    }  //------------------------------------------->注意,方法与方法之间不需要添加逗号
    sing(song) {
      console.log(this.uname + '唱' + song);
    }
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 18);
console.log(ldh); // Star {uname: "刘德华", age: 18}
ldh.sing('冰雨'); // 刘德华唱冰雨
类的继承 extends
class Father {
      constructor(surname) {
        this.surname= surname;
      }
      say() {
        console.log('你的姓是' + this.surname);
       }
}

class Son extends Father{  // 这样子类就继承了父类的属性和方法
}
var damao= new Son('刘');
damao.say();      //结果为 你的姓是刘
super关键字
访问父类
//定义了父类
class Father {
   constructor(x, y) {
     this.x = x;
     this.y = y;
   }
   sum() {
   console.log(this.x + this.y);
	}
 }
//子元素继承父类
    class Son extends Father {
   		 constructor(x, y) {
    		super(x, y); //使用super调用了父类中的构造函数
    	}
    }
    var son = new Son(1, 2);
    son.sum(); //结果为3
调用父类里的方法
class Father {
    say () {
        return '我是爸爸'
    }
}

class Son extends Father{
    say() {
        // console.log('我是儿子')
        console.log(super.say() + '的儿子')
    }
}

var son = new Son()
son.say()

注意:

  1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的

  2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)

  3. 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用

  4. 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象

  5. 时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用.

  • constructor中的this指向的是new出来的实例对象

  • 自定义的方法,一般也指向的new出来的实例对象

  • 绑定事件之后this指向的就是触发事件的事件源

静态成员和实例成员

实例成员
 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
     this.sing = function() {
     	console.log('我会唱歌');
    }
}
var ldh = new Star('刘德华', 18);
console.log(ldh.uname);//实例成员只能通过实例化的对象来访问
静态成员
 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
     this.sing = function() {
     console.log('我会唱歌');
    }
}
Star.sex = '男'; 
var ldh = new Star('刘德华', 18);
console.log(Star.sex);//静态成员只能通过构造函数来访问

原型对象prototype

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
Star.prototype.sing = function() {
	console.log('我会唱歌');
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
ldh.sing();//我会唱歌
zxy.sing();//我会唱歌

对象原型

每一个实例对象都有一个__proto__属性,他指向了构造函数中的prototype 原型对象,之所以我们对象可以使用构造函数中的prototype 原型对象的属性和方法,就是因为对象中有这个__proto__属性 它的意义就是为对象查找提供了一个方向或者说是一条路线
__proto__对象原型和原型对象 prototype 是等价的

方法的查找规则: 首先先看实例对象身上是否有 这个方法,如果有就执行这个对象上的这个方法
如果没有 这个方法,因为有__proto__ 的存在,就去构造函数的原型对象prototype身上去查找这个方法

constructor构造函数

function Star(uname, age) {
     this.uname = uname;
     this.age = age;
 }
 Star.prototype.sing = function() {
     console.log('我会唱歌');
 };
 Star.prototype.movie = function() {
     console.log('我会演电影');
 }
 var ldh = new Star('刘德华', 18);
 console.log(ldh.__proto__.constructor); // Star { }
function Star(uname, age) {
     this.uname = uname;
     this.age = age;
 }
 // 很多情况下,我们需要手动的利用constructor 这个属性指回 原来的构造函数
 Star.prototype = {
 // 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
   constructor: Star, // 手动设置指回原来的构造函数
   sing: function() {
     console.log('我会唱歌');
   },
   movie: function() {
     console.log('我会演电影');
   }
}
var zxy = new Star('张学友', 19);
console.log(zxy.__proto__.constructor) // Star { }

原型链

 function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Star.prototype.sing = function() {
            console.log('我会唱歌');
        }
        var ldh = new Star('刘德华', 18);
        // 1. 只要是对象就有__proto__ 原型, 指向原型对象
        console.log(Star.prototype);
        console.log(Star.prototype.__proto__);
        // 2.我们Star原型对象里面的__proto__原型指向的是 Object.prototype
        console.log(Object.prototype.__proto__);
        // 3. 我们Object.prototype原型对象里面的__proto__原型  指向为 null

通过原型为数组扩展内置方法

Array.prototype.sum = function () {
       var sum = 0;
       for (var i = 0; i < this.length; i++) {
       sum += this[i];
    }
      return sum;
 };

var arr = new Array(1, 2, 3)
console.log(arr.sum());

继承

子构造函数继承父构造函数中的属性

// 1. 父构造函数
function Father(name, age) {
          // this 指向父构造函数的对象实例
            this.name = name;
            this.age = age
        }
// 2 .子构造函数
function Son(name, age) {
           // this 指向子构造函数的对象实例
           // 使用call方式实现子继承父的属性
            Father.call(this, name, age)
        }
var son = new Son('刘德华', 18)
console.log(son);

子构造函数继承父构造函数中的方法

 // 借用父构造函数继承属性
        // 1. 父构造函数
        function Father(uname, age) {
            // this 指向父构造函数的对象实例
            this.uname = uname;
            this.age = age;
        }
        Father.prototype.money = function() {
            console.log(100000);

        };
        // 2 .子构造函数 
        function Son(uname, age, score) {
            // this 指向子构造函数的对象实例
            Father.call(this, uname, age);
            this.score = score;
        }
        // Son.prototype = Father.prototype;  这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
        Son.prototype = new Father();
        // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
        Son.prototype.constructor = Son;
        // 这个是子构造函数专门的方法
        Son.prototype.exam = function() {
            console.log('孩子要考试');

        }
        var son = new Son('刘德华', 18, 100);
        console.log(son);
        console.log(Father.prototype);
        console.log(Son.prototype.constructor);

改变函数内的this指向方法

call()

call() 可以调用函数, 可以修改this的指向,使用call()的时候 参数一是修改后的this指向,参数2,参数3…使用逗号隔开连接

function fn(x, y) {
     console.log(this);
     console.log(x + y);
	}
  var o = {
  	name: 'andy'
  };
fn.call() // 调用函数
fn.call(o, 1, 2);//调用了函数此时的this指向了对象o,
apply

apply() 可以调用函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。

参数使用数组传递

var o = {
	name: 'andy'
}
 function fn(a, b) {
      console.log(this);
      console.log(a+b)
};

fn.apply(o,[1,2])//此时的this指向的是对象o,参数使用数组传递 运行结果为3

var arr = [1, 66, 3, 99, 4];
// var max = Math.max.apply(null, arr);
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max, min);
bind

bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数

var o = {
 name: 'andy'
 };

function fn(a, b) {
	console.log(this);
	console.log(a + b);
};
var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数
f();//调用新函数  this指向的是对象o 参数使用逗号隔开

var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
  btns[i].onclick = function() {
    this.disabled = true;
    setTimeout(function() {
      this.disabled = false;
    }.bind(this), 2000);
  }
}

严格模式中的变化

严格模式对 Javascript 的语法和行为,都做了一些改变。

'use strict'
num = 10 
console.log(num)//严格模式后使用未声明的变量
--------------------------------------------------------------------------------
var num2 = 1;
delete num2;//严格模式不允许删除变量
--------------------------------------------------------------------------------
function fn() {
 console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined
}
fn();  
---------------------------------------------------------------------------------
function Star() {
	 this.sex = '男';
}
// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
var ldh = new Star();
console.log(ldh.sex);
----------------------------------------------------------------------------------
setTimeout(function() {
  console.log(this); //严格模式下,定时器 this 还是指向 window
}, 2000);  
----------------------------------------------------------------------------------
a = 1;
a = 2;
function fn(a, a) {  // 严格模式下函数里面的参数不允许有重名
  console.log(a + a);
};
fn(1, 2);

正则表达式

常见

用户名:/1{3,16}$/
手机号:/^1[3|4|5|7|8]\d{9}/
昵称:/2{2,8}$/

^ 代表以这个符号后面的数开头的

$ 代表以这个符号前面结尾的

a到z , 0到9 , 可用符号_- 最小3位最大16位

正则表达式的创建

方式一:通过调用RegExp对象的构造函数创建
var regexp = new RegExp(/正则表达式/);
console.log(regexp);
方式二:利用字面量创建 正则表达式
var rg = /123/;

测试正则表达式

test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。

var rg = /123/;

console.log(rg.test(123));//匹配字符中是否出现123  出现结果为true
console.log(rg.test('abc'));//匹配字符中是否出现123 未出现结果为false
var rg = /^[a-z0-9_-]{3,16}$/;
// 检测输入的是否符合条件
console.log(rg.test('jqj123')); // true
var rg=/^[^a-zA-Z0-9_-]$/    // [^] 中括号里加^ 代表取反
console.log(rg.test('a'));  // false
console.log(rg.test('!'));  // true

分组 exec

exec 获取分组内容

a 起得分组名
var reg = /<div>(?<a>123)<\/div>/   // 正则表达式
var str = `<div>123</div>`   
console.log(reg.exec(str).groups.a); // 123
// 获取分组名的内容

exec 获取满足正则的内容并分组 ()

返回一个数组,索引0 是符合正则的那个字符串 索引1 是第一个分组

var str = '<div>{{name}}今年{{ age }}岁了</div>'
var reg = /{{\s*([a-zA-Z]+)\s*}}

var res1 = reg.exec(str);
console.log(res1); //  [ {{name}} , name ] 
// 只能找到字符串里第一个符合正则表达式的 无法找到第二个只有把第一个改了之后才可以找到第二个符合的
str = str.replace(res1[0], res1[1])

var res2 = reg.exec(str)
console.log(res2);   [ {{ age }} , age ] 

// 没有符合正则表达式的就返回 null

提取 match

字符串.match(正则表达式) 可以对字符串进行提取操作,返回值是一个数组

// 提取字符串str中的邮箱内容,注意 需要在正则的最后添加匹配模式g不要设置严格匹配
var str = '小明:大神么么哒,正好是我想要的,我的邮箱是xiaoming@qq.com小红:我老公最爱看这个了,我想给他一个惊喜,么么么哒,邮箱是xiaohong@sina.com我:好人一生平安,邮箱是wuyou@163.com';

var arr = str.match(/\w+@\w+.\w+/gi)
console.log(arr);

或 |

正则里面的或者 符号 |

var rg = /^\d{3}-\d{8}|\d{4}-\d{7}$/
console.log(rg.test('0100-6344898'));

边界符

边界符说明
^表示匹配行首的文本(以谁开始)
$表示匹配行尾的文本(以谁结束)

量词符

量词符用来设定某个模式出现的次数。

量词说明
*重复0次或更多次
+重复1次或更多次
?重复0次或1次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次

预定义类

预定义类指的是某些常见模式的简写方式.

预定类说明
\d相当于[0-9]
\D相当于[ ^ 0-9]
\w相当于[A-Za-z0-9]
\W相当于[ ^ A-Za-z0-9]
\s匹配空格(包括换行符,制表符,空格等) 相等于[\t\r\n\v\f]
\S匹配非空格 相等于[ ^ \t\r\n\v\f]

正则替换

replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式。
replace(/激情|gay/gi, '**')
// g 全局匹配
// i 忽略大小写

ES6新增语法

let

  • let关键字就是用来声明变量的
  • 使用let关键字声明的变量具有块级作用域
  • 在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的
  • 防止循环变量变成全局变量
  • 使用let关键字声明的变量没有变量提升
  • 使用let关键字声明的变量具有暂时性死区特性
暂时性死区

利用let声明的变量会绑定在这个块级作用域,不会受外界的影响

var tmp = 123;
if (true) { 
     tmp = 'abc';
     let tmp; 
} 
经典面试题
var arr = [];
 for (var i = 0; i < 2; i++) {
     arr[i] = function () {
         console.log(i); 
     }
 }
 arr[0](); // 2
 arr[1](); // 2
let arr = [];
 for (let i = 0; i < 2; i++) {
     arr[i] = function () {
         console.log(i); 
     }
 }
 arr[0]();  // 0
 arr[1]();  // 1

**经典面试题图解:**此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的,函数执行时输出的是自己上一级(循环产生的块级作用域)作用域下的i值.

小结
  • let关键字就是用来声明变量的
  • 使用let关键字声明的变量具有块级作用域
  • 在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的
  • 防止循环变量变成全局变量
  • 使用let关键字声明的变量没有变量提升
  • 使用let关键字声明的变量具有暂时性死区特性

const

声明常量,常量就是值(内存地址)不能变化的量

具有块级作用域

声明常量时必须赋值

常量赋值后,值不能修改

既然是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据类型,不能更改地址值

// const 声明的复杂数据类型可以更改里面的值 但不可重新赋值 也就是说不可改地址
const arr = [100, 200]
arr = ['a', 'b']  // 不可直接赋值
arr[0] = 200  // 可更改
arr[1] = 300  // 可更改
console.log(arr); // 200 300

let、const、var 的区别

  • 使用 var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
  • 使用 let 声明的变量,其作用域为该语句所在的代码块内,不存在变量提升
  • 使用 const 声明的是常量,在后面出现的代码中不能再修改该常量的值

解构赋值

  • 解构赋值就是把数据结构分解,然后给变量进行赋值
  • 如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
  • 数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用逗号隔开
  • 利用解构赋值能够让我们方便的去取对象中的属性跟方法
数组解构
let [a, b, c] = [1, 2, 3];

 console.log(a)//1
 console.log(b)//2
 console.log(c)//3
//如果解构不成功,变量的值为undefined
对象解构
let person = { name: 'zhangsan', age: 20 }; 
let { name, age } = person;
console.log(name); // 'zhangsan' 
console.log(age); // 20
let {name: myName, age: myAge} = person; // myName myAge 属于别名
console.log(myName); // 'zhangsan' 
console.log(myAge); // 20

箭头函数

() => {} //():代表是函数; =>:必须要的符号,指向哪一个代码块;{}:函数体

const fn = () => {}//代表把一个函数赋值给fn
  • 箭头函数中不绑定this,箭头函数中的this指向是它所定义的位置,可以简单理解成,定义箭头函数中的作用域的this指向谁,它就指向谁
  • 箭头函数的优点在于解决了this执行环境所造成的一些问题。比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题
面试题
var age = 100;

var obj = {
	age: 20,
	say: () => {
		alert(this.age)  // 100
	}
}

obj.say();//箭头函数this指向的是被声明的作用域里面,而对象没有作用域的,所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域

剩余参数 …

剩余参数语法允许我们将一个不定数量的参数表示为一个数组,不定参数定义方式,这种方式很方便的去声明不知道参数情况下的一个函数

function sum (first, ...args) {
     console.log(first); // 10
     console.log(args); // [20, 30] 
 }
 sum(10, 20, 30)
剩余参数和解构配合使用
let students = ['wangwu', 'zhangsan', 'lisi'];
let [s1, ...s2] = students; 
console.log(s1);  // 'wangwu' 
console.log(s2);  // ['zhangsan', 'lisi']

防抖

// 声明计时器
var timer = null

// 先清除计时器
clearTimeout(timer)
// 在启用定时器
timer = setTimeout(function () {
      getSuggestList(kw)// 请求函数
 }, 500)

节流

// 定义节流阀 设为空
var timer = null
//  绑定事件
$(document).on('mousemove', function (e) {
   // 判断节流阀是否为空
   if (timer) { return }
   // 开启计时器
  timer = setTimeout(function () {
    // 执行代码  ...
      
    // 执行完计时器重新设为空
    timer = null  
 }, 16)

  1. a-z0-9_- ↩︎

  2. \u4e00-\u9fa5 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值