函数this指向 闭包 递归

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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值