this指向及函数调用(闭包与递归简介)

160 阅读3分钟

一.函数this三种指向

环境对象this :谁'调用'我,我就指向谁

普通函数 :函数名( ),this指向window

构造函数: new 函数名( ),this指向new创建实例对象

对象方法: 对象名.方法名( ),this指向对象

*小技巧:没点没new是window,有new是实例,有点是点左边的对象

二.函数上下文调用

默认情况下,函数内部的this不能主动修改,如果需要修改,则需要使用函数上下文方式调用

函数上下文:函数作用域

1.call()调用函数

函数名.call(修改后的this,参数1,参数2......)

实际开发中,ES6新增语法用于伪数组转真数组: Array.from(伪数组)

万能数据类型检测:Object.prototype.toString.call(数据)

2.apply()调用函数

函数名.apply(修改后的this, 数组或伪数组 )

ES6求最大值 ...展开运算符,作用和apply类似,也会自动遍历数组,然后逐一传参

3.bind()调用函数

函数名.bind(修改后的this)

    * 不会立即执行函数,而是得到一个修改this之后的新函数。
    * bind一般用于修改: 定时器函数、事件处理函数
    
setTimeout(function () {
  console.log(this)
}.bind({
  name: "1111"
}), 2000)

4.call和apply和bind三者区别

相同点 : 作用一致,修改函数this指向

不同点 :
传参方式不同 : call是按照顺序单个传参, apply是数组/伪数组传参

执行机制不同 : call和apply会立即执行函数,而bind不会立即执行而是得到修改this的新函数

三.闭包

1.闭包closure是什么 :

        a. 闭包 是一个 访问其他函数内部变量 的 函数
        b. 闭包 = 函数 + 上下文引用

2.闭包作用 : 解决变量污染

四.递归

1.递归函数: 一个函数 在内部 调用自己

* 递归作用和循环类似的,也需要有结束条件

2.浅拷贝与深拷贝

浅拷贝 : 拷贝地址,修改拷贝后的数据对原数据有影响

深拷贝 : 拷贝数据,修改拷贝后的数据对原数据没有影响

//浅拷贝: 拷贝地址
        // let newObj = obj
        // 修改拷贝后的数据,原数据也会修改
        // newObj.name = '李四'
        // console.log( obj,newObj)

json实现深拷贝

//深拷贝 : 拷贝数据
        //(1)先把js对象 -> JSON字符串   (JSON会自动帮你深拷贝)
        // let jsonStr = JSON.stringify( obj )
        //(2)再把 JSON字符串 -> js对象
        // let newObj = JSON.parse( jsonStr )

        let newObj = JSON.parse(JSON.stringify(obj))

递归实现深拷贝

    let obj = {
            name: '张三',
            age: 20,
            sex: '男',
            hobby: ['吃饭', '睡觉', '学习'],
            student: {
                name: "班长",
                score: 90
            }
        }

        //使用递归函数
        function copy(obj, newObj) {
            for (let key in obj) {
                if (obj[key] instanceof Array) {
                    //声明一个空数组,然后继续拷贝数组里面的数据
                    newObj[key] = []
                    //递归调用继续拷贝 数组
                    copy(obj[key], newObj[key])
                } else if (obj[key] instanceof Object) {
                    //声明一个空对象
                    newObj[key] = {}
                    //递归调用继续拷贝 对象
                    copy(obj[key], newObj[key])
                } else {
                    newObj[key] = obj[key]
                }
            }
        }
        //创建一个空对象,然后深拷贝
        let newObj = {}
        copy(obj, newObj)