es5-函数高级

函数的定义和调用

  • 命名函数
    function fn(){};
  • 函数表达式 匿名函数
    var fun = function(){};
  • 对象定义 new Function(‘参数1’,’参数2’,’函数体’)
    var f = new Function('a','b','console.log("a+b")');
    f(1,2); // 结果为 3
    Function里面的参数必须是字符串格式
    这种方法执行效率低,不方便书写,很少使用
    所有函数都是Function的实例对象

函数内this的指向

  • this的指向是在调用函数时确定的,调用方式的不同决定了this指向的不同
  • 一般指向调用者
调用方式 this指向
普通函数调用 window
构造函数调用 实例对象 原型对象里的方法也指向实例对象
对象方法调用 该方法的所属对象
事件绑定方法 绑定事件对象
定时器函数 window
立即执行函数 window

改变函数内部的this指向

  • call() 调用函数,改变函数this指向
    fun.call(this指向,参数)
    
        var o = {
            name: 'andy'
        }
    
        function fn(a, b) {
            console.log(this);
            console.log(a+b);
        }
    
        fn.call(o, 1, 2) // 输出3  this指向o
    
    call的主要作用可以实现继承
  • apply() 调用函数,改变函数this指向
    fun.apply(this指向,[数组参数])
    该方法传递的值必须包含在数组里面
    返回值就是函数的返回值,因为它就是调用函数
    
        var o = {
            name: 'andy'
        }
    
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
    
        fn.apply(o, [1, 2]) // 输出3 this指向o
    
        // apply主要应用 比如可以借助apply借助数学内置对象求最大值
        
        var arr = [1,66,99,4]
        var max = Math.max().apply(Math,arr);
        console.log(max) //输出99
  • bind() 不会调用函数,但是可以改变函数内部的this指向
    fun.bind(this指向,参数,参数)
    返回指定的this值和初始化参数改造的原函数拷贝
    
    // 使用
        var o = {
            name: 'andy'
        }
    
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
    
        var fn1 = fn.bind(o, 1, 2);
        fn1(); // 输出3      this指向o
        // 不会调用原来的函数,可以改变原函数内部的this指向,
        // 返回的是原函数this改变之后的新函数

严格模式

  • 消除了js中语法不合理的地方,减少了怪异的行为
  • 消除了代码运行时一些不安全之处保证代码运行安全
  • 提高编译器效率,增加运行速度
  • 禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的js做好铺垫,比如加一些保留字,class enum export extends import super 不能做变量名
    // 可以应用到整个脚本,或个别函数中
    // 可以分为脚本开启严格模式,为函数开启严格模式

为脚本开启严格模式

  • 方法
    // 在代码最前面声明语句
    <script>
    "use strict"; // 开启严格模式
    // 下面的代码都会以严格模式执行
    </script>

为某个函数开启严格模式

  • 方法
    <script>
        function fn() {
            "use strict";
        }
        // 为fn函数开启严格模式
    </script>

严格模式的问题

  • 变量必须声明才可以打印赋值
  • 不可以随意删除声明的变量
  • 严格模式下定义的函数的this指向的是undefined
  • 构造函数必须通过new来调用,this指向全局对象
  • 定时器里的this指向的是window
  • 函数不可以有重名的参数
  • 函数不允许放在非函数代码块中

高阶函数

  • 接收一个函数作为参数
  • 返回值为函数
function fn(a, b, callback) {
    console.log(a + b);
    callback && callback();
}
fn(1, 2, function() {
    console.log('我是最后调用的');
})

闭包

  • 在函数内可以调用其他函数作用域中的变量可以成为闭包
  • 闭包延长了变量的作用范围
// 函数可以访问其他函数作用域中的变量就可以称为闭包
function fn() {
    var num = 10;

    function fun() {
        console.log(num);
    }
    fun();
}
fn();
// fun的作用域访问了 fn的局部变量,这就是闭包
  • 通过闭包在全局作用域访问函数的局部作用域
    // fn外面的作用域可以访问fn内部的局部变量
    function fn() {
        var num = 10;
    
        return function fun() {
            console.log(num);
        }
        
    }
    var fun = fn();
    fun();
  • 案例
    // 点击输出索引号
    <body>
        <ul class="nav">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
    </body>
    <script>
        var lis = document.querySelectorAll('.nav li'); // 注册事件
        for (var i = 0; i < lis.length; i++) { // 循环绑定点击事件
            (function(i) {
                lis[i].addEventListener('click', function() {
                    console.log(i); // 打印索引号
                })
            })(i)
        }
    </script>

递归函数

  • 如果一个函数在内部可以调用自己,那么这个函数就是递归函数
    // 用递归求1----- n的阶乘
    
        function fn(n) {
            if (n == 1) {
                return 1
            }
            return n * fn(n - 1)
        }
        console.log(fn(3))

浅拷贝

  • 浅拷贝只拷贝一层
// 实现浅拷贝 可以用for循环把数据拷贝到o 当然也有语法糖
Object.assign(拷贝的对象, 被拷贝的对象);
// 就是后者把数据拷贝给前者

    o = {}
    obj = {
        id: 1,
        name: 'andy',
        msg: {
            age: 18
        }

    }
    Object.assign(o, obj);

    o.msg.age = 19 // 更改o对象的msg下的age属性
    console.log(o);
    console.log(obj); // obj这个对象也会被更改

深拷贝

  • 深拷贝是把每一级的数据都会拷贝上
    // 实现深拷贝
    
    
        function fn(new_o, obj) {
            for (var i in obj) {
                item = obj[i]
                // 判断当前i是不是数组
                if (obj[i] instanceof Array) {
                    // 是的话 以当前i为key 创建一个数组
                    new_o[i] = [];
                    // 进行递归 后将递归的值全部写入到当前i中
                    fn(new_o[i], item)
                    // 判断当前i是否为对象
                } else if (obj[i] instanceof Object) {
                    // 是对象的话 以当前i为key 创建一个对象
                    new_o[i] = {};
                    // 进行递归,后将递归出的值全部写入当前i中
                    fn(new_o[i], item)
                } else {
                    // 如果都不是就直接赋值
                    new_o[i] = item
                }
            }
    
        }
        fn(o, obj)
        console.log(o.msg == obj.msg); // 返回false

本博客所有文章是以学习为目的,如果有不对的地方可以一起交流沟通共同学习 邮箱:1248287831@qq.com!