单信js——4难点部分

递归:

递归函数是指在函数内部调用函数自身。
注意:
递归的出口:什么情况下结束调用
递归的入口:什么情况下调用自已

//递归实现阶乘
var fn=function(n){
if(n==1){
return 1; //递归的出口
}
return n*arguments.callee(n-1); //在函数内部可以使用 arguments.callee调用函数自身
}

var result=fn(5); //54321
console.log(result);

函数的惰性载入

是用来减少每次代码执行时的重复性的分支判断,通过对对象的重新定义来屏蔽原来对象的分支判断。
惰性方式相对于初次加载立即执行,可以在需要时来初始化,避免页面初次加载就执行而消耗性能。实现让机器在执行时,也学会了去改进自己的代码了

匿名函数

就是指没有名称的函数。
匿名函数可以赋给一个变量,也可以直接执行。
如果只需要执行一次,就不需要赋给变量
如果需要多次调用执行,就赋给变量,用变量多次调用
匿名函数出现的目的就只有两个:
打包一段需要立即执行的程序逻辑。
缩小函数内部成员作用域,同时函数本身也会在执行完毕后,脱离引用被回收,减少全局污染。

第二天回顾

1. JSON
    1) 什么是JSON?
        JSON是一种轻量级的数据交换格式,天然就是JS对象
        
    2) JSON的格式
        {"键名":值, "键名":值}
        
        获取JSON数据的原则:
            看到大括号就是对象:  obj.name  obj['name']
            看到中括号就是数组: arr[0]
            
    3) JSON的转换
        //JSON格式的字符串转换成对象
        var obj=JSON.parse(字符串);
        
        //将对象转换成字符串
        var str=JSON.stringify(对象);
        
2. 作用域
    1) 什么是作用域?
        作用域是指函数的封装特性产生独立的运行(上下文)环境,运行环境就可以将变量或函数划分为不同的作用域。
        
    2) 作用域的划分
        a. 全局作用域
            函数外定义的数据都是全局作用域,在任意地方都能被访问
            
        b. 局部作用域
            函数内定义的数据都是局部作用域,只能在当前函数内被访问
            
        c. 块级作用域
            ES5以前没有块级作用域的概念, 可以使用IIFE实现块级作用域
            ES6以后就有了块级作用域,可以使用 let关键词实现
            
    3) 作用域链
        正常情况下,函数内可以访问上一级函数的数据,上一级函数可以再访问上一级作用域的数据,
这就形成了作用域链条,可以实现最里的语句访问最顶层的数据。

3. IIFE
    1) 什么是IIFE?
        IIFE就是【立即执行   函数表达式】,相当于块级作用域,将一段代码封装函数加载时立即执行,执行完以后立即销毁,不会有任何遗留。
        
    2) IIFE的写法
        (function(){
            ...代码段...
        })();
        
        false || function(){
        }();

4. 闭包
    1) 什么是闭包?
        闭包是一种作用域的体现,体现正常情况下函数外不能访问函数内的数据,函数内可以访问函数外的数据。
        闭包是一种特殊写法,将函数内的子函数暴露在全局上,子函数可以被全局调用,又可以访问到上一级函数的数据。
        实现函数外的语句可以函数内的数据。
        
    2) 闭包的作用?
        函数外访问函数内的数据。
        封装插件、封装功能模块...
        
    3) 闭包的写法
        (function(){
            var i=0;
            function _show(){
                ....
            }
            
            window.show=_show;
        })();
        
        (function(){
            var i=0;
            window.show=function(){
                return i++;
            }
        })();
        
        var show=(function(){
            var i=0;
            return function(){
                return i++;
            }
        })();

this关键字

  1. 全局的this
    全局的this就是window对象
    console.log(window); //Window
    console.log(this); //Window
    console.log(this === window); //true
  2. 函数中的this
    原则:谁调用函数,函数中的this就指向谁
    提醒:如果开启了严格模式,this不会指向window对象
    function fn(){
    console.log('函数中的this:', this); //Window
    }
    fn(); //因为这里是window在调用fn函数,所以指向window
  3. 对象方法中的this
    指向对象本身
    var obj={};
    obj.name="张三疯";
    obj.show=function(){
    console.log(this===obj); //true
    };
    obj.show();
  4. 构造函数中的this
    指向new创建的实例
    function Person(name,age){
    this.name=name;
    this.age=age;
    console.log(this);
    }
    var p1=new Person('李四爷',88); //Person {name: "李四爷", age: 88}
    var p2=new Person('王小五',18); //Person {name: "王小五", age: 18}

借来的this:

所有的函数都拥有三个方法,可以实现将函数中的this指向新对象(修改函数中this的指向):

  • call 主动式将函数中的this指向新对象,调用一次立即执行一次
    语法: 函数.call(对象, 参数1, 参数n);

  • apply 效果同上
    语法:函数.call(对象, [参数1,参数2,参数n]);

  • bind : 被动式的改变this的指向
    语法: 回调函数.bind(对象,参数1,参数2);

下面例子,使用call或者 apply方法修改this的指向
var p1={"name":"周瑜"};
p1.phone=function(){
console.log(this.name + '给小乔打1个小时电话');
}
p1.phone(); //周瑜给小乔打1个小时电话


var p2={"name":"曹操"};
p1.phone.apply(p2);  //曹操给小乔打1个小时电话

var p1={"name":"周瑜"};
p1.phone=function(target,time){
console.log(this.name + '给'+target+'打'+time+'电话');
}
p1.phone('小乔','10个小时');   //周瑜给小乔打10个小时电话

var p2={"name":"曹操"};
p1.phone.apply(p2,['刘备','1分钟']); //在调用方法时还可以传参数
//曹操给刘备打1分钟电话

call apply bind的区别:

  • 相同点:
    都是函数的原型方法,可以改变函数中this的指向
    第一个参数都写要将this修改到的目标
    都可以传递参数

  • 不同点:
    call apply是主动式的,修改this指向时立即调用一次
    bind是被动式的,只修改this的指向,不执行
    call的参数直接列举在对象后面,apply以数组形式传参数

this、apply、call、bind的详细教程

面试题: call()、apply()和bind()的区别:
都能改变this的指向
call()/apply()是立即调用函数
bind():绑定完this后,不会立即调用当前函数,而是将函数返回,因此后面还需要再加()才能调用。
PS:bind()传参的方式和call()一样。
分析:
为什么ES5中要加入bind()方法来改变this的指向呢?因为bind()不会立即调用当前函数。
bind()通常使用在回调函数中,因为回调函数并不会立即调用。如果你希望在回调函数中改变this,不妨使用bind()。

你可能感兴趣的:(单信js——4难点部分)