zoukankan      html  css  js  c++  java
  • 关于:上下文调用模式 的学习整理

    前言:如果有错误或者疑问的地方,请大家指正,我会持续更新!

    上下文(Context),就是函数调用所处的环境,上下文调用,也就是自定义设置this的含义。

    在其他三种调用模式中,函数/方法在调用的时候,this的值都是指定好了的,我们没办法自己进行设置,如果尝试去给this赋值,会报错。

    上下文调用的语法

    第一种, apply
    函数名.apply(对象, [参数]);
    
    第二种, call
    函数名.call(对象, 参数);
    
    上面两种方式的功能一模一样,只是在传递参数的时候有差异。

    功能描述:
    1. 语法中的函数名表示的就是函数本身,使用函数调用模式的时候,this默认是全局对象

    2. 语法中的函数名也可以是方法(如:obj.method),在使用方法模式调用的时候,this默认是指当前对象

    3. 在使用applycall的时候,默认的this都会失效,this的值由applycall的第一个参数决定

    补充说明:

    1. 如果函数或方法中没有this的操作, 那么无论什么调用其实都一样.

    2. 如果是函数调用foo(), 那么有点像foo.apply( window ).

    3. 如果是方法调用o.method(), 那么有点像o.method.apply( o ).

    参数问题

    callapply在没有后面的参数的情况下(函数无参数, 方法无参数) 是完全一样的.

    如下:

    function foo() {
     console.log( this );
    }
    foo.apply( obj );
    foo.call( obj );
    

    第一个参数的使用规则:

    1. 如果传入的是一个对象, 那么就相当于设置该函数中的 this 为参数

    2. 如果不传入参数, 或传入 null. undefiend 等, 那么相当于 this 默认为 window

    
    foo();
    
    foo.apply();
    
    foo.apply( null );
    
    foo.call( undefined );
    
    1. 如果传入的是基本类型, 那么 this 就是基本类型对应的包装类型的引用

      • number -> Number

      • boolean -> Boolean

      • string -> String

    第二个参数的使用规则

    在使用上下文调用的时候, 原函数(方法)可能会带有参数, 那么这个参数在上下文调用中使用第二个( 第 n 个 )参数来表示

    
    function foo( num ) {
    
     console.log( num );
    
    }
    
    foo.apply( null, [ 123 ] );
    
    // 等价于
    
    foo( 123 );

    上下文调用模式的应用

    上下文调用只是能修改this, 但是使用的最多的地方上是函数借用.

    1. 将伪数组转换为数组

    传统的做法:

    var a = {};
    a[ 0 ] = 'a';
    a[ 1 ] = 'b';
    a.length = 2;
    
    // 使用数组自带的方法 concat
    // 如果参数中有数组会把参数数组展开
    // 语法: arr.concat( 1, 2, 3, [ 4, [ 5 ] ] );
    // 特点:不修改原数组
    var arr = [];
    var newArr = arr.concat( a );
    

    由于a是伪数组, 只是长得像数组. 所以上面的代码不能成功,不能使用concat方法。

    但是apply方法有一个特性, 可以将数组或伪数组作为参数。(IE8不支持伪数组操作)

    foo.apply( obj, 伪数组 ); // IE8 不支持
    

    利用apply方法,可以写出以下

    //将伪数组 a 作为 apply 的第二个参数
    var newArr = Array.prototype.concat.apply( [], a )
    

    处理数组转换, 实际上就是将元素一个一个的取出来构成一个新数组, 凡是涉及到该操作的方法理论上都可以。

    push方法
    //用法:
    arr.push( 1 ); //将这个元素加到数组中, 并返回所加元素的个数
    arr.push( 1, 2, 3 ); //将这三个元素依次加到数组中, 返回所加个数
    
    var a = { length: 0 }; // 伪数组
    a[ a.length++ ] = 'abc'; // a[ 0 ] = 'abc'; a.length++;
    a[ a.length++ ] = 'def';
    
    // 使用一个空数组, 将元素一个个放到数组中即可
    var arr = [];
    arr.push( a ); // 此时不会将元素展开, 而是将这个伪数组作为一个元素加到数组中
    // 再次利用 apply 可以展开伪数组的特征
    arr.push.apply( arr, a );
    // 利用 apply 可以展开伪数组的特性, 这里就相当于 arr.push( a[0], a[1] )
    

    2. 求数组中的最大值

    传统的做法

    var max = arr[ 0 ];
    for ( var i = 1; i < arr.length; i++ ) {
        if ( arr[ i ] > max ) {
            ...
        }
    }
    

    在 js 中的Math对象中提供了很多数学函数Math.max( 1,2,3 )

    还是利用 apply 可以展开数组的特性

    var arr = [ 123456,12345,1234,345345,234,5 ];
    Math.max.apply( null, arr );
    

    3.借用构造函数继承

    function Person ( name, age, gender ) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    
    // 需要提供一个 Student 的构造函数创建学生对象
    // 学生也应该有 name, age, gender, 同时还需要有 course 课程
    function Student ( name, age, gender, course ) {
        Person.call( this, name, age, gender );
        this.course = course;
    }




  • 相关阅读:
    android编译时出现org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:compileDebugJavaWithJavac'.错误
    jdk1.8中获取项目绝对路径和项目路径
    okhttp在https连接中出现java.net.ProtocolException: Expected ':status' header not present的解决办法
    mybatis+sqlserver中返回非自增主键
    华为手机不能连接android studio进行调试的解决办法
    android中service启动后台程序
    getContentLength() 指为 -1 的解决办法
    svn服务器搭建(windows)
    Caliburn.Micro 杰的入门教程3,事件和参数
    Caliburn.Micro 杰的入门教程1(翻译)
  • 原文地址:https://www.cnblogs.com/lin-dong/p/6494981.html
Copyright © 2011-2022 走看看