four js高级 apply call bind 作用域 闭包 沙箱 递归

apply和call方法

作用都可以改变this的指向

没有传参数

apply和call方法中如果没有传入参数,或者传入的是null,那么调用该方法的函数的this指向是默认的window

参数

f1.apply(null, [100,200]) 数组传入参数

f1.call(null,100,200) 一个个传入

f1.apply(对象, [100,200])那么f1中的原型指向变成了 传入的这个对像

f1.call(对象,100,200)

apply和call调用的话 如果 不是写在指向原型的函数里面 相当于一次调用

并没有真正的这个对像原型里继承

运用的地方

只要想使用别的对象的方法 或者属性 运用在自己生就可以 进行调用

apply和call实际上实在 Function里面

bind方法

改变this指向

参数中没有传入对象或者null

此时的this指向默认是window

var ff = f1.bind(10, 20);
将f1复制了一份给 ff

参数可以在复制的时候传入 也可以在复制之后传

有传入对象

此时 就相当于 将f1复制一份 原型指向 per这个原型

此时 ff 就可以调用f1的属性和方法 也可以调用 per里面的属性和方法了

var ff = f1.bind(per, 10, 20);

此时只能拿到属性 不能得到方法 f1是函数

var per = new Person(10);
    var stu = new Student(20);
    //复制了一份
    var ff1 = per.play.bind(stu);
    ff1();

上面这种方式 意思就是 将per.play复制了一份 然后指向是stu

此时的参数是stu的参数为准

per.play.bind(stu)bind后面还有没有参数 是看per.play有没有参数

还有一点就是复制完 只是在 per.play这个方法里获取到stu里的参数

stu里面的参数 在 new里面进行传入

目前的调用方式

实例对象的方法 调用实例对象

函数 调用实例对象

bind的应用

parseInt()
是向下取整
function ShowRandon() {
        this.number = parseInt(Math.random() * 10 + 1);
    };
    ShowRandon.prototype.show1 = function() {
        //这里使用window全局调用了  本来this是window
        //bind改变了this指向  现在this是实例对象 
        window.setInterval(this.show2.bind(this), 1000);
    };
    ShowRandon.prototype.show2 = function() {
        console.log(this.number)
    };
    var ar = new ShowRandon();
    ar.show1();

函数中的几个成员

函数中有一个那么属性 函数的名字,name属性是只读 不能修改

函数中有一个arguments属性 实参的个数

函数有一个length属性 函数定义的时候形参个数

函数中有一个caller属性 在其他函数调用这个函数 就会显示 否则为null

函数作为参数

函数作为参数,如果是命名函数,那么只传入命名函数的名字,没有括号

定时器传入函数

函数作为返回值使用

有return 可以用变量来接收

typeof 变量 判断数据类型

var obj = {};
console.log(obj instanceof Object);

获取某个对象的数据类型样子

Object.prototype.toString.call(对象)//此时得到的就是这个对象的类型

var str = "abj";
console.log(Object.prototype.toString.call(str)

排序

数组的排序 从小到大

var arr = [1, 100, 20, 200, 40, 50, 120, 10];
    //排序---函数作为参数使用,匿名函数作为sort方法的参数使用,那么此时的匿名函数中有两个参数,
    arr.sort(function(obj1, obj2) {
        if (obj1 > obj2) {
            return 1;
        } else if (obj1 == obj2) {
            return 0;
        } else {
            return -1;
        }
    })
    console.log(arr)
    1变  -1不变

数组中字符串的排序

函数作为返回值的扩展案例

排序的调用 在案例11 有详细讲解

自己做一下表格的排序

作用域和作用域链和预解析

作用域

变量 局部 全局

作用域 局部 全局

js没有块级作用域 一堆大括号中定义的变量,这个变量可以在大括号外面被使用

while(true){
//      var num=10;
//      break;
//    }
//    console.log(num);
这里是可以被访问到的
if(){
    num = 10;
}
外部可以访问到

函数中定义的变量是局部变量 外部访问不到

#####作用域链

从里往外找 直到找到这个变量 没找到就是未定义

预解析

就是在浏览器解析代码之前,把变量的声明和函数的声明提前到该作用的最上面

leg

变量的提前 未定义

console,log(num);

var num = 100;

函数的提前调用
  • 声明方式的函数可以被调用

f1();

function f1(){

console.log(“解决”);

}

  • 函数表达式 提前调用则报错 var f2 f2()出错

    原因 这个可以看作是变量 变量提前 就不会执行

f2();

var f2 = function (){

console.log(“哈哈哈”);

}

闭包

概念: 函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就形成了闭包 暂时不严谨

闭包模式: 函数模式的闭包 对象模式的闭包

闭包的作用: 缓存数据 延长作用域链

闭包的优点和缺点 : 缓存数据

#####函数模式的闭包 :函数中有函数

#####对象模式中的闭包: 函数中有一个对象

function f3() {
        var num = 10;
        var obj = {
            age: num,
        };
        console.log(obj.age);
    }
    f3();

闭包的小案例

function f2() {
        num = 10;
        return function() {
            num++;
            return num;
        }
    }
    var ff = f2();
    console.log(ff());
    console.log(ff());
    console.log(ff());

这边有对num进行了缓存

输出 11 12 13 闭包 缓存数据

闭包模式产生相同的随机数

如果想缓存数据 ,就把这个数据放在外层函数和里层函数的中间位置

闭包的作用: 缓存数据 没有及时释放变量

局部变量在函数使用完后,就会自动的被释放

闭包 后 里面的局部变量使用作用域链就会被自动的延长

闭包案例实现点赞

function my$(tagName) {
        return document.getElementsByTagName(tagName);
    }
    //闭包缓存
    function getValue() {
        var value = 1;
        return function() {
            value++;
            //return value;
            this.value = "(赞" + value + ")";
        }
    }
    var btnObj = my$("input");
    for (var i = 0; i < btnObj.length; i++) {
        btnObj[i].onclick = getValue();
    }
将闭包函数的返回值赋给  点击事件  相当于点击事件原本的function

沙箱

环境 黑盒 虚拟的环境 小环境 自调用函数
//沙箱---小环境
//    (function () {
//      var num=10;
//      console.log(num);
//    })();
//
//    //沙箱---小环境
//    (function () {
//      var num=20;
//      console.log(num+10);
//    }());

沙箱小案例

str = str.substr(2);删掉字符串前两个

递归

函数中调用函数自己 此时就是递归 递归一定要有结束的条件

var i = 0;

    function f1() {
        i++;
        if (i < 5) {
            f1();
        }
        console.log("哈哈哈");
    }
    f1();

递归小案例

递归函数n个数字和

function getSum(x) {
        if (x == 1) {
            return 1;
        }
        return x + getSum(x - 1);
    }

执行的过程如下

* 执行过程:
     * 代码执行getSum(5)--->进入函数,此时的x是5,执行的是5+getSum(4),此时代码等待
     * 此时5+getSum(4),代码先不进行计算,先执行getSum(4),进入函数,执行的是4+getSum(3),等待, 先执行的是getSum(3),进入函数,执行3+getSum(2),等待,先执行getSum(2),进入函数,执行 2+getSum(1);等待, 先执行getSum(1),执行的是x==1的判断,return 1,所以,
     * 此时getSum(1)的结果是1,开始向外走出去
     * 2+getSum(1) 此时的结果是:2+1
     * 执行:
     * getSum(2)---->2+1
     * 3+getSum(2) 此时的结果是3+2+1
     * 4+getSum(3) 此时的结果是4+3+2+1
     * 5+getSum(4) 此时的结果是5+4+3+2+1

递归函数 求 一个是数字各个位数上的数字之和

//递归案例:求一个数字各个位数上的数字的和:  123   --->6 ---1+2+3
    //523
    function getEverySum(x) {
        if (x < 10) {
            return x;
        }
        //获取的是这个数字的个位数
        return x % 10 + getEverySum(parseInt(x / 10));
    }
    console.log(getEverySum(1364)); //5

//递归案例:求斐波那契数列 就是 第三个数字是前两个数字之和

猜你喜欢

转载自blog.csdn.net/qq_38964133/article/details/88377559