1.函数this指向
1.this:环境对象。谁调用我,就指向谁。
2.js中函数有三种调用方法,this三种指向(面试)
(1)普通函数:函数名() this->window
(2)构造函数:new 函数名() this->new创建的实例对象
(3)对象的方法:对象名.方法名() this->对象
2.上下文调用
2.1 call()
(1)函数名.call(修改的this指向,参数1,参数2...)
function fn(a,b){
console.log(a+b)
console.log(this)
}
// 1.函数名.call(this指向参数1,参数2...)
fn.call({name:'张三'},10,20)
2.2 call()应用:万能数据检测类型
1.typeof 数据:两种数据类型无法检测
null和数组,得到的都是object
2.万能检测数据类型:Object.prototype.toString.call(数据)
3.面试点:
(1)请说出下列代码运行结果:type[]
(2)是否能得到array,如果不能的话如何解决
// (1)值类型
let str='abc'
let num=10
let bol=true
let und=undefined
let nul=null
// (2)引用类型
let arr=[10,20,30]
let fn=function(){}
let obj={name:'张三'}
console.log(typeof str) //'string'
console.log(typeof num) //'number'
console.log(typeof bol) //'boolean'
console.log(typeof und) //'undefined'
console.log(typeof nul) //'object'
console.log(typeof arr) //'object'
console.log(typeof fn) //'function'
console.log(typeof obj) //'object'
console.log(Object.prototype.toString.call(str)) //[object String]
console.log(Object.prototype.toString.call(num)) //[object Number]
console.log(Object.prototype.toString.call(bol)) //[object Boolean]
console.log(Object.prototype.toString.call(und)) //[object Undefined]
console.log(Object.prototype.toString.call(nul)) //[object Null]
console.log(Object.prototype.toString.call(arr)) //[object Array]
console.log(Object.prototype.toString.call(fn)) //[object Function]
console.log(Object.prototype.toString.call(obj)) //[object Object]
2.3 apply()
(2)函数名.apply(修改的this,数组/伪数组)
function fn(a,b){
console.log(a+b)
console.log(this)
}
// 2.函数名.apply(修改的this,数组/伪数组)
fn.apply({name:'李四'},[10,20])
2.4 apply()场景:伪数组转真数组
1.伪数组:有数组三要素(下标,元素,长度),没有数组的方法
//伪数组的本质是对象
let obj={
0:20,
1:55,
2:60,
3:80,
length:4
}
// 需求:伪数组转为真数组
// 这里只是借助apply()传参特点,不需要修改this
// 因为代码arr.push()原本的this就是arr,所以apply()修改的参数不变,还是arr
let arr=[]
arr.push.apply(arr,obj)
console.log(arr)
// ES6方式
// 静态方法:Array.from(伪数组)
let newArr=Array.from(obj)
console.log(newArr)
2.5 apply()场景:求数组最大值
// 1.以前的写法:擂台思想
// 2.Math.max.apply()
let arr=[22,44,67,99,55]
let max=Math.max.apply(Math,arr)
console.log(max)
// ES6方式
// ...展开运算符,相当于自动遍历数组每一个元素,类似于apply()
let max1=Math.max(...arr)
console.log(max1)
2.6 bind()
// 函数名.bind(修改的this)
// bind()不会立即执行函数,而是得到一个修改this之后的新函数
// (1)定时器 (2)事件处理函数
function fn(a,b){
console.log(a+b)
console.log(this)
}
let newFn=fn.bind({name:'王五'})
newFn(50,60)
2.7 bind()场景:修改定时器的this
1.定时器函数中的this默认一定是window
2.要想修改定时器函数中的this,需要用bind()
let fn=function(){
console.log(this)
}
let newFn=fn.bind({name:'王五'})
// newFn:取值(函数地址) newFn():调用函数得到返回值
setTimeout(newFn,2000)
// 一行代码显示
setTimeout(function(){
console.log(this)
}.bind({name:'王五'}),2000)
面试题:call(),apply(),bind()三者区别:
相同的:作用一致,都是修改函数的this指向
不同点:
1.传参方式不同:call是单个传参,apply是数组/伪数组传参
2.执行机制不同:call和apply会立即执行,bind不会立即执行,而是得到一个修改this之后的新函数
3.闭包
3.1 闭包介绍
1.闭包:是一个访问其他函数内部变量的函数
闭包组合= 函数 + 上下文引用
2.闭包作用:解决变量污染
3.闭包应用场景:闭包实际开发中一般用于 回调函数
function fn(){
let num=10
// fn1()函数访问了其他函数fn的内部变量。 fn1 + num组合就叫闭包
function fn1(){
console.log(num)
}
fn1()
}
fn()
4.递归介绍
1.递归函数:在函数调用自己
2.递归应用:
(1)浅拷贝与深拷贝
(2)遍历dom树
4.1 浅拷贝与深拷贝:json
面试点:浅拷贝与深拷贝
浅拷贝:拷贝的是地址,修改拷贝后的数据,对原数据有影响
深拷贝:拷贝的是数据,修改拷贝后的数据,对原数据没有影响
(1)转json:let obj1=JSON.parse(JSON.stringify(obj))
let obj={
name:'张三',
age:20,
hobby:['学习','上课','敲代码']
}
// 浅拷贝:拷贝的是地址,修改拷贝后的数据,对原数据有影响
// let obj1=obj
// obj.name='李四'
// console.log(obj,obj1)
// 深拷贝:拷贝的是数据,修改拷贝后的数据,对原数据没有影响
// (1)先把对象->JSON
// let json=JSON.stringify(obj)
// (2)后把json->对象
// let obj1=JSON.parse(json)
let obj1=JSON.parse(JSON.stringify(obj))
obj1.name='李四'
obj1.hobby[0]='游戏'
console.log(obj,obj1)
(2)递归
let obj={
name:'张三',
age:20,
hobby:['学习','上课','敲代码'],
learn:{
name:'王五',
age:18
}
}
// 声明深拷贝函数
function kaobei(obj,newObj){
// 遍历obj数据
for(let key in obj){
// 如果obj[key]是数组,需要继续遍历拷贝数据
if(obj[key] instanceof Array){
// (1)给newObj声明空数组
newObj[key]=[]
// (2)循环遍历拷贝数组每一个元素
// for(let i in obj[key]){
// newObj[key][i]=obj[key][i]
// }
kaobei(obj[key],newObj[key])
}else if(obj[key] instanceof Object){
newObj={}
kaobei(obj[key],newObj[key])
}else{
newObj[key]=obj[key]
}
}
}
// 声明一个空对象
let newObj={}
kaobei(obj,newObj)
newObj.name='李四'
newObj.hobby[0]='游戏'
console.log(obj,newObj);