美文网首页
this引用的指向

this引用的指向

作者: 赵一矛 | 来源:发表于2018-04-27 09:49 被阅读0次

在javascript的函数中,除了函数声明时定义的形参之外,每个函数还可以接收另一个隐藏的参数:this,又称this引用。 这里就讲一下this的作用以及不同场景下它的不同指向。this的值(即它的指向)取决于调用的方式。在javascript中this指向大致有四种情况:

  1. 无任何前缀的函数调用时,this指向顶层对象或者全局对象,浏览器里是window(nodejs里是global).
function fn(){
  console.log(this);
}
fn();//global{}
  1. 方法调用的时候,this指向方法所在的对象。
var robot={
  name:"cup",
  say:function(){
    console.log(this.name);
  }
};
robot.say();//cup
  1. 构造函数里,this指向新生成的实例
function Robot(name){
  this.name=name;
  this.say=function(){
    console.log(this.name);
  }
};
robot_1=new Robot('bower');
robot_1.say();//bower
robot_2=new Robot('cup');
robot_2.say();//cup
  1. apply/call调用的时候,this指向apply/call方法中的第一个参数。
var robot_1={name:'cup'};
var robot_2={name:'bower'};
function say(){
  console.log(this.name);
}
say.apply(robot_1);//cup
say.call(robot_2);//bower

在最外层代码中,this引用引用的是全局对象. 在函数内,this引用根据函数调用的方式不同而有不同的含义.
通过类和对象这课程的学习我们知道,方法是对象的属性所引用的函数.下面是一个关于关于方法和this引用的具体例子解析.
1.方法内的this调用

//对象定义
var robot = {
    name : "cup",
    say : function() { console.log( "Hi, I'm " + this.name + "."); }
}
robot.say()            // 打印结果为 Hi, I'm cup.
//对象robot是被调用的对象,say是方法。

首先是将对象赋给了变量robot。这个对象有两个属性。属性name的值为"cup",属性say的值是一个函数。该函数称作say方法。 被调用的方法say内的关键字this引用指向了被调用的对象robot。
2.函数内的this调用

var robot = {
    name : "cup",
    say : function() { console.log( "Hi, I'm " + this.name + "."); }
}
var fn = robot.say;
// 将robot.say引用的函数赋值给全局变量 fn.

fn()                        // 打印结果为 Hi, I'm .
// 执行函数(全局的方法),this引用了全局对象,由于全局对象没有name属性,所以没有取到值.

根据我们之前讲的,现在这个函数由于是无任何前缀的直接调用的,this应该是指向了全局对象,我们确认一下this是否指向了全局对象

var robot = {
    name : "cup",
    say : function() { console.log( "Hi, I'm " + this.name + "."); }
}
var fn = robot.say;
//将robot.say引用的函数赋值给全局变量 fn.
//相当于给全局对象定义了一个属性fn,并赋予robot.say所指代的函数.

var name = "bower",
//相当于给全局对象定义了一个属性name,赋值为"bower",在浏览器里,上面这行代码等价于 window.name = "bower";

fn()                    // 打印结果为 Hi, I'm bower.
//执行函数fn(相当于调用全局对象的fn方法),执行时this引用了全局对象.所以this.name的值是"bower".

函数的apply与call方法

所有的函数都默认包含apply和call两种方法,调用函数的apply或call方法,就相当于调用该函数.不考虑函数内的this引用的话,这和类似于 say() 这样的普通调用方式是一样的。 而apply和call的功能是,通过传参的方式,强制函数内的this指定某一对象。this引用的会被指向apply/call的第一个参数。
下面是一个使用了apply方法和call方法的函数调用的例子。

function say(){ console.log(this.name); }
var robot = {name:"cup"};

say.apply(robot)            // 打印结果为cup
//通过apply调用函数say。函数内的this引用引用了对象robot。

say.call(robot)            // 打印结果为cup
//通过call调用函数say。函数内的this引用引用了对象robot。

下面是一个使用了apply方法和call方法的对某对象的方法进行调用的例子。

var robot_1 ={
  name:"cup",
  say:function(){
          console.log(this.name)
          }
};
var robot_2 ={ name:"bower" };

robot_1.say() //打印结果为cup

robot_1.say.apply(robot_2)            // 打印结果为bower
//通过apply调用robot_1.say方法。方法内的this引用引用了robot_2

robot_1.say.call(robot_2)                // 打印结果为bower
//通过call调用robot_1.say方法。方法内的this引用引用了robot_2

apply与call之间的不同之处在于两者对其他参数的传递方式。
对于apply来说,剩余的参数将通过数组来传递,而call是直接按参数列表传递。

function say(age, gender){console.log("My name is " + this.name + ",I'm a " + age + " years old " + gender + ".")}

say.apply({name:"cup"}, [12, "boy"])            //打印结果为 My name is cup,I'm a 12 years old boy.
// this.name = "cup", age = 12, gender = "boy"  作为第二个参数的数组中的元素都是函数say的参数,按顺序依次对应

say.call({name:"cup"}, 12, "boy")                //打印结果为 My name is cup,I'm a 12 years old boy.
// this.name = "cup", age = 12, gender = "boy"  从第二个参数起的参数都是函数say的参数,按顺序依次对应

事例:

function Tool(name, usage){
    this.name = name;
    this.usage = usage;
    this.get_info = function() {console.log("This is " + this.name + ", the usage of it is " + this.usage + ".")}
}
var cycling = new Tool("cycling","transport");

function display(date){
    console.log(this.name+","+this.usage+","+date)
}

display.apply(cycling,["1970"]);
//cycling,transport,1970

自定义类

一个典型的定义类的方法

function Car(x,y){ 
  this.x = x;
  this.y = y;
  this.run = function(x_increase, y_increase){
      this.x += x_increase;
      this.y += y_increase;
  }
  this.show = function(){
      console.log("( " + this.x + "," + this.y + " )");
  }
}

通过上述代码,我们就拥有了一个名为Car的“类”。它有两个成员变量x和y还有一个成员函数run。那么我们就可以像用Object一样使用它:

var a_car = new Car(2,4); //获得了一个坐标为(2,4)的Car对象,x为2,y为9
a_car.run(10,5);          //a_car.x变成了12,a_car.y变成了9
a_car.show();             //打印结果

相关文章

  • this引用的指向

    在javascript的函数中,除了函数声明时定义的形参之外,每个函数还可以接收另一个隐藏的参数:this,又称t...

  • this引用的指向

    在javascript的函数中,除了函数声明时定义的形参之外,每个函数还可以接收另一个隐藏的参数:this,又称t...

  • 指向指针的引用

    引用本身不是对象,因此不能定义指向引用的指针。但指针是对象,所以存在指针的引用。 要理解r的类型到底是什么,就简单...

  • weak和unowned

    一、循环引用 如图所示的情况中,john指向的对象强引用了unit4A指向的对象,而unit4A指向的对象又强引用...

  • java GC(基于Hotspot)

    什么是垃圾 没有任何引用指向的对象就是垃圾(循环引用时,没有其他引用指向也是垃圾) 如何查找垃圾 引用计数器: 每...

  • Java 的小白学习笔记三(数据类型和变量类型)

    Java两大数据类型 一、内置数据类型 二、引用类型 引用类型指向一个对象,指向对象的变量是引用变量。引用变量声明...

  • 引用计数与ARC

    一、引用计数原理引用计数就是表示多少个指针指向这个对象,当新的指针指向该对象时引用计数加1,当指针不再指向该对象时...

  • 深拷贝 & 浅拷贝

    浅拷贝:大多数对象都引用(指向)其他对象,不复制引用对象。新复制的对象只指向现有的引用对象。 例如 NSArray...

  • 多态的再理解

    对象的多种形态 1.引用形态 父类的引用可以指向本类的对象 父类的引用可以指向子类的对象 Animal d=new...

  • 引用分类,WeakHashMap,IdentityHashMap

    引用分类 强引用:StrongReference,引用指向对象,gc(Garbage Collection)运行时...

网友评论

      本文标题:this引用的指向

      本文链接:https://www.haomeiwen.com/subject/xceylftx.html