一、this关键字
this的关键含义
(1)全局的this:指向window对象
console.log(this)
(2)普通函数中的this:指向window对象
function fn() {
console.log(this)
}
fn()
(3)自调用函数中的this:指向window对象
(function() {
console.log(this)
})()
(4)定时器中的this:指向window对象
setTimeout(function() {
console.log(this)
}, 1000)
(5)事件函数中的this:指向.前面的事件源
<button id="btn">按钮</button>
btn.onclick = function() {
console.log(this)
}
//this指向:<button id="btn">按钮</button>
(6)对象方法中的this:指向.前面的调用对象
var obj = {
name: '张三',
age: 12,
eat: function () {
console.log(this) //指向obj对象
}
}
obj.eat()
this关键含义的修改
js提供了3个函数来强行修改this关键字的含义:
call方法:调用函数以及改变函数中的this
1.函数名.call(要改变的this指向的对象,实参1,实参2...)
function fn(a, b) {
var c = a + b
console.log(c)
console.log(this)
}
fn(1, 2) // 3 window
fn.call(document, 2, 3) // document 5
fn.call(null, 5, 6) // window 11
//第一个参数为null,则将函数中的this指向window
2.数组方法.call(伪数组):通常用于将伪数组转成数组,方便调用数组方法处理元素
var divs = document.querySelectorAll('div')
var arr = []
var newDivs = arr.slice.call(divs, 0)
console.log(newDivs);
3.对象.toString.call(数据):检测数据为对象时的精准类型
var obj = {}
console.log(obj.toString.call(123));
console.log(obj.toString.call('abc'));
console.log(obj.toString.call(true));
console.log(obj.toString.call(undefined));
console.log(obj.toString.call(null));
console.log(obj.toString.call([]));
console.log(obj.toString.call({}));
console.log(obj.toString.call(function(){}));
console.log(obj.toString.call(/^abc$/));
console.log(obj.toString.call(new Date()));
apply方法:apply和call的作用是相同的,唯一不同的地方,在于传递实参
函数名.apply(要改变的this指向的对象,[实参1,实参2...])
function fn(a, b) {
var c = a + b
console.log(c)
console.log(this)
}
fn(1, 2) // 3 window
fn.apply(document, [2, 3]) // document 5
注意:以上两个方法,在修改了函数中的this关键字之后,并直接调用该函数;
bind方法:复制函数,并改变新函数中的this。
函数名.bind(要改变的this指向的对象); //返回新函数
var obj = {
name: '张三',
eat: function() {
console.log(this);
}
}
var fn = obj.eat.bind()
fn() // window
// 将定时器中的this改为document
document.onclick = function() {
setTimeout((function() {
console.log(this)
}).bind(this), 1000)
}
注意:使用bind()方法改变函数中this关键字指向之后,会把修好的函数引用地址给返回,因此需要再次调用返回之后的函数引用地址;
call、apply和bind之间的区别:
call和apply的区别:两个函数都是改变函数执行上下文的,但是传的参数不同
bind和其他两个差别在:传参与call相同,但是bind会返回一个新的函数
二、ES6
变量
es6新增了两个类似于var的关键字来定义变量,分别是let和const。
let关键字:
Let和var的区别:
let不允许重复定义
let定义的变量没有预解析
let定义的变量会自己创建一个块级作用域,将自己的作用域限制在大括号中。(let自带块级作用域,全局定义的变量也不在window中,if和for中的let变量不能在大括号外面访问了)
const关键字:
const关键字也是用来定义变量的,具备let的所有特性;
const定义的变量的值不能修改;
const声明的时候必须赋值
箭头函数
//箭头函数是对匿名函数的简写
let fn = () => {
console.log(111)
}
//带参数的写法
let fn = (a,b) => {
console.log(a+b)
}
//当只有一个形参的时候,可以省略小括号,当大括号中只有一行代码的时候可以省略大括号
let fn = a => console.log(a)
//这行代码中如果有return就必须省略return
let fn = a => a+1
箭头函数定义好以后就已经知道箭头函数中this的含义了,且不可改
箭头函数中没有this指向,该函数中的this指向跟它的上下文有关,也就是说函数的上下文中的this指向哪里,那么箭头函数中的this也就指向哪里;箭头函数中的this和调用无关,主要是和在哪里创建有关;
箭头函数中没有argument对象
函数默认值
es6的函数中可以定义默认值:
function add(a,b=2){
return a + b;
}
console.log(add(5)); //7
//箭头函数改写为
let add=(a,b=2)=>a+b;
console.log(add(5)) //7
模板字符串
var s=`字符` // 使用反引号
模板字符串和普通字符串区别:
(1)前者中的内容可以换行,保持字符串中的换行和空格;后者不行
(2)前者里面可以直接书写变量,后者不行
模板字符串中可以识别变量,使用美元符大括号:${变量}
解构赋值
作用:可以快速的从数组或对象中提取元素
[ ]:解构数组
let arr = [1,2,3];
let [num1] = arr; //从数组中拿出第一个元素赋值给num1变量
let [num1,num2,num3] = arr; //解构多个元素
//多维数组解构
let arr = [1,2,3,[4,5,6]];
let [a,b,c,[aa,bb]] = arr;
console.log(aa,bb); // 4 5
//利用解构给两个数交换位置
let num1=10
let num2=20
let [num2,num1]=[num1,num2]
console.log(num1,num2)
{ }:解构对象
let obj = {
name:"张三",
age:12,
sex:"男",
wife:{
name:"翠花",
age:11,
}
}
let {name} = obj;
let {name:n} = obj; //可以有别名
console.log(n) //有别名则输出name无效
let {name,age,sex}=obj; //解构多个变量
let {wife:{name:wname}} = obj; //多级解构
注意:在解构对象时,{ }中变量名,需要跟对象中的键名同名
展开运算符
// 可以将数组中的元素展开
let arr = [1,2,3];
console.log(...arr)
// 可以将多个变量赋值给多个形参
let arr = [1,2,3];
function fn(a,b,c){
console.log(a,b,c); // 1 2 3
}
fn(...arr);
// 对象可以在对象中展开,进行合并;但是不能直接展开对象输出
const obj = {
name:"Jack",
age:20,
sex:"男",
}
const obj1 = {
...obj,
wife:{
name:"Rose",
age:18
}
}
console.log(obj1);
合并运算符
//将多个实参合并为一个数组
function fn(...arr){
console.log(arr);
}
fn(1,2,3); // [1,2,3]
//箭头函数可以改为
let fn=(...arr)=>console.log(arr)
fn(1,2,3)
对象的简写方式
当前对象中的键名跟键值的变量名相同时,可以只写一个键名;
对象中的方法,可以直接简写成方法名(){ }
var name1='丽丽'
var age1=18
var o1={
name1,
age1,
fn1:function(){
console.log("hello")
},
fn2(){
console.log("world")
}
}
Map构造函数
里面存储在的数据类似于对象,只不过它的键名可以是任意数据类型
var m=new Map()
//()参数是二维数组
var obj = {
sex: '男'
}
var m = new Map([['name', '张三'], [obj, '对象']])
console.log(m);
// map的结构使用[],其中的数据也必须是[],在里面的[]中第一个为键,第二个为值,如果只有键没有值,默认的值为undefined。
Map对象中常用的属性和方法:
map.size:获取元素个数,返回数字。
map.get(key):根据键名获取指定的键值;如果获取一个map中不存在的键,返回undefined。
map.set(key,value):给map对象设置键值对;如果map中已经有了当前指定的键,后面的值会覆盖前面的值。
map.delete(key):删除指定的键值;返回boolean,代表是否删除成功;删除map中不存在的键,返回false。
map.keys():获取所有键的集合。
map.values():获取所有值的集合。
map.clear():清空所有键值对。
map.has(key):查找当前键名是否在map对象中存在,返回boolean。
map.forEach((value,key)=>{ }):遍历map对象中所有元素。
Set构造函数
存储的数据结构跟数组非常相似,里面的元素是唯一不重复的
var s1=new Set(数组或伪数组)
//数组去重
var s = new Set([1,1,2,2,2,3,4,2,1])
console.log(s);
Set对象中常用的方法和属性:
set.size:获取当前set对象中元素的个数
set.add():给set对象添加元素;添加元素时,会检查set对象中是否存在该元素,如果存在,则不添加;如果不存在,则添加;
set.delete():删除set对象中指定的元素
set.clear():清空set对象中所以元素
set.has():查找当前元素是否在set对象中存在,返回boolean
set.forEach(item=>{ }):遍历set对象中所有元素
注意:set对象中的元素不能通过下标直接获取
for、for...in、forEach、for...of之间的区别
for循环:
可以遍历数组;但是不可以遍历对象;可以使用break,continue语句跳出循环;
forEach:
可以遍历数组、Set集合、Map集合;但是不可以遍历对象、字符串;也不可以使用break, continue, return控制循环;
for in:
可以遍历对象、数组(遍历数组的时候会将数组的下标作为键)、字符串;也不可以使用break, continue, return控制循环;
for of:
可以遍历数组、字符串、Set集合、Map集合;但是不可以遍历对象;