zoukankan      html  css  js  c++  java
  • 前端见微知著JavaScript基础篇:你所不知道的apply, call 和 bind

    在我的职业生涯中,很早就已经开始使用JavaScript进行项目开发了。但是一直都是把重心放在了后端开发方面,前端方面鲜有涉及。所以造成的一个现象就是:目前的前端知识水平,应付一般的项目已然是足够的,但是火候尚缺,没有深入的进行研究,以至于总是谈论起来就发现自己半瓶子哐当的水平。为了解决这种尴尬的局面,决心潜心研究一段时间JavaScript,以下知识为本人学习过程中的总结,虽然以本人水平可能招致贻笑大方之果,但是更盼抛砖引玉之实。

    在JavaScript中,我们调用一个普通的方法,可以通过如下的方式来进行:

    //全局公共调用方式
    function greetingMorning()
    {
          alert("Hello Morning!");
    }
    greetingMorning();
    //局部调用方式
    var greetingWorld =function() {
          alert("Hello World!");
    } greetingWorld();
    //自调用方式
    (function(){
          alert("Hello ChaoYang!");
    })();

    那么上面就是一般的三种调用方式,前两种都会在window对象上面进行附加,不同之处就在于,第一种是直接利用function进行声明方式,属于公共调用方式;第二种是利用var关键字进行申明的方式调用。也就是说,第一种申明方式所申明的函数,无论在函数体之前或之后调用,都没问题。而第二种申明方式所申明的函数,只能在函数体之后调用:

    //正确,可以这么调用
    greetingMorning();
    function greetingMorning()
    {
         alert("Hello Morning!");
    }
    //错误,提示找不到方法
    greetingWorld();
    var greetingWorld =function()
    {
         alert("Hello World!");
    }

    在这里,我们需要注意的第一个坑就是局部变量加不加var关键字的问题:

    function greetingLucy()
    {
          name ="lucy";
          alert("Hello "+name);
    }
    greetingLucy();
    alert(name);

    这里我们的执行结果,第一次会输出: Hello lucy, 第二次会输出: lucy。 这很奇怪,为什么name我写到了方法里面,按理来说已经是局部变量了,为什么还是会输出结果呢?其实在JavaScript中,在方法体内,如果不加var关键字的话,会将此变量默认为全局变量。这也是为什么会输出结果的原因了。

    那么知道了函数执行的一般方法,那么我们来看函数的执行的特殊方法。

    如上所述,我们直接利用 (); 的方式可以出发函数的立即执行。但是这种执行,其实在大多数情况下是无法改变this关键字的作用域的,由于this默认指向的就是已经实例化过的window对象,所以很多时候当我们需要更改this的作用域的时候,我们就不得不引入 apply, call 关键字 以及 bind 关键字。 我们先来讲解他们的基本用法。

    首先,对于apply方法:

    //不带参数,我们apply了this,可以看出我们改变了this的作用域 //从原本的window对象,指向了greetingLucy
    function greetingLucy()
    {
          var name ="lucy"; alert("Hello "+name);
    }
    greetingLucy.apply(this);
     
    //带两个参数
    function greeting(name, age)
    {
          alert("Hello "+ name +""+ age +" !");
    }
    greeting.apply(this,["lucy",23]);

    可以看出,使用apply的时候,其中第一个参数一定要指向需要应用的对象,之后的多个参数需要写成数组的方式。

    再来看看call方法:

    function greetingLucy()
    {
          var name ="lucy";
          alert("Hello "+name);
    }
    greetingLucy.call(this);
     
    function greeting(name,age)
    {
          alert("Hello "+ name +""+ age +" !");
    }
    greeting.call(this,"lucy",25);

    可以看出,使用call的时候,第一个参数也是需要指向被调用的对象,之后的多个参数可以直接写就行。

    从这里我们可以看出,apply和call都会改变this的作用域,至于更详细的信息,我会放到第二节去讲解。

    下面我们来看看bind方法。

    var color ="red";
    var obj = {color:"blue"};
    function sayColor()
    {
          alert(this.color);
    }
    var nw = sayColor.bind(obj);
    //执行
    nw();

    这里会输出什么呢? 这里会输出“blue”。那为什么不会输出red呢? 其实在这里,this关键字有个很重要的特点,那就是: 谁调用我,我指向谁。由于bind方法的调用,会导致this指向的改变,从window对象变成了指向obj对象。所以这里会拿obj对象中的color来执行。

    从上面的例子我们也可以看出,bind方法不会导致函数的立即执行,需要触发才可以执行。

    为什么bind不会立即执行呢? 我们可以执行 alert(nw)看出返回给我们的结果:

    function bound sayColor(){[native code]}

    这说明bind以后返回的nw对象,就是一个函数,并且还是未执行的函数,如果我们想执行,就需要加上 ();

    好了,这里就是我所理解的 apply call bind的用法了。

    其实他们的用法很基础,但是他们可以改变this作用域的这个特点倒是杀伤力惊人。后面的章节我会重点讲解this,争取将其吃透。敬请期待。

  • 相关阅读:
    php中 include 、include_once、require、require_once4个语言结构的含义和区别
    PHP yield 分析,以及协程的实现,超详细版(上)
    wordpress里的bloginfo()与get_bloginfo()
    CSS定位中“父相子绝”
    Apache 的 httpd.conf 详解
    apache的<directory>语句以及属性的含义
    你必须了解的Session的本质(PHP)
    Linux常用命令
    vmware中配置CentOS
    程序员可能会遇到的一些名词
  • 原文地址:https://www.cnblogs.com/scy251147/p/4839060.html
Copyright © 2011-2022 走看看