js-浅析this指向

来源:互联网 发布:火烧赤壁的网络意思 编辑:程序博客网 时间:2024/06/08 10:34

    在理解this的绑定过程之前,首先要理解调用位置:调用位置就是函数在代码中被调用的位置(而不是声明的位置)。对于正常的函数调用,this的绑定分为以下几种:
1. 默认绑定

    如果函数是在全局上直接使用不带任何修饰的函数引用进行调用,此时只能使用默认绑定。即在非严格模式下,this指向window。而如果是在严格模式下,则不能对全局对象进行默认绑定,此时的this会指向undefined。如下:

  function fn(){       console.log(this.a);   }   var a = 2;   fn();

    此时console.log的结果为2
2. 隐式绑定

    隐式绑定是需要考虑函数是否是作为对象的一个属性值进行调用。此时this会指向包含该函数的对象。严格来说,对象属性引用链上只有上一层或者最后一层在调用位置上起作用。如下,console的打印结果为1:

var a = 42;function fn(){    console.log(this.a);};var obj1 = {    a:1,    fn:fn};obj1.fn();

    值得注意的是,隐式绑定会发生丢失绑定对象的现象。即调用对象不再像前文一样直接运行对象中属性值中的函数。而是先将该属性值赋值给一个变量,后运行这个赋值后的变量。此时this将不再指向包含该属性值的对象。而是决定于赋值后的变量在哪调用。如下:

var a  = 42;function fn(){    console.log(this.a)};var obj1 = {    a:1,    fn:fn};var b = obj1.fn;b();

    此时console的结果为42.原因就在于b虽然是obj1.fn的引用,但是实际上它引用的是fn函数本身。因此b()此时是一个不带任何修饰符的函数,this的指向将按照默认绑定规则进行绑定。

    除了这种情况,回调函数进行参数传递时,也会发生上述情况。

  1. 显式绑定

        通过一些方法,可以将this强制绑定到固定元素上。这种操作便是显式绑定。常用的办法为apply()和call()。这两个方法的第一个参数是一个对象,是给this准备的,接着在调用函数的时候,将this绑定在该对象上。这两个方法的区别在于call()的参数为一个一个的参数。而apply(),其参数为数组形式,调用函数中接收时为arguments。

        显式绑定中有一种写法是可以解决绑定丢失的情况。即在函数调用的时候使用call或者apply,强制将函数的this绑定到call或apply的第一个参数上。即

function fn(){    console.log(this.a);}var obj = {a:2};var bar = function(){    foo.call(obj);}bar();

    此时foo的this被强制绑定在obj上,打印结果就为2。

     在ES5中提供了一种方法,Function.prototype.bind。其z作用原理也跟上述写法类似。

function fn(something){    return this.a + something;}var obj = {    a :2}var bar = fn.bind(obj);var b = bar(3);
  1. new绑定

        在面向对象编程(oop)中,都会使用new来调用一些函数。而这些函数被称为构造函数。构造函数是用来初始化新创建的对象。当我们使用new来调用一个函数时,该函数内部的this会指向一个对象。在没有重新定义返回值的前提下,该函数返回的对象和内部指向的对象是同一个对象。

function fn(userName,age){   //var object = new Object();   // this = new Object;    this.name = userName;    this.age = age;}var girl = new fn('lily','23');

    上述代码中注释中的代码只是为了演示,不具有可操作性。实际上在调用构造函数中,this所指向的对象是由js内部创建,而非外部编程可操作。