详解JavaScript中this关键字的用法

this是函数内部的一个特殊对象,this引用的是函数据以执行的环境对象(关于环境对象我们会在文章最后作补充说明),在调用函数前this的值并不确定,不同的调用方式会导致this值的改变。

window.num = 22;
var o = {num: 11};
function sayNum(){
  alert(this.num)
}
sayNum();//22
o.sayNum = sayNum;
o.sayNum();//11

记住:函数名仅仅是一个包含指针的变量而已。因此即使是在不同的环境中执行,全局的sayNum()函数与o.sayNum()指向的仍然是同一个函数。

1.全局作用域中调用函数时
全局作用域中调用,this对象引用的是window
匿名函数的执行具有全局性,因此其this对象通常也指向window

function fn1(){
  console.log(this);
}

fn1();

2.通过new操作符调用
this引用的是实例对象

function Person(name){
  this.name = name;
}
Person.prototype.printName = function(){
  alert(this.name);//Byron
};

var p1 = new Person('Byron');

3.作为对象的方法调用
this引用的是该对象

var obj1 = {
  name: 'Byron',
  fn : function(){
    console.log(this);
  }
};

obj1.fn();

4.间接调用
call和apply
每个函数都包含两个非继承而来的方法:call()和apply()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。也就是说,直接调用函数,调用时指定执行环境是谁

window.color = 'red';
var o = {color: 'blue'};
function sayColor(){
  alert(this.color);
}
sayColor.call(this);//red
sayColor.call(window);//red
sayColor.call(o);//blue

(1)apply方法
接收两个参数,一个是在函数中运行函数的作用域,另一个是参数数组。

(2)call方法
call方法与apply方法相同,区别在于接收参数的方式不同,对于call方法而言,第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。

function fn(){
   console.log(this)//windwow
   function InnerFn(){
     console.log(this)
   }
   InnerFn.call(this)//window
}
fn();
 function fn0(){
   console.log(this)//window
}
function fn1(){
   fn0.call(this);
   console.log(this);//window
}
fn1();
function fn0(){
 console.log(this)//object
}
var o = {
  fn1: function fn1(){
    fn0.call(this);
    console.log(this);//object
  }
}
o.fn1();

5.bind方法
这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。也就是说会返回一个新函数,并且使函数内部的this为传入的第一个参数

window.color = 'red';
var o = {color : 'blue'};
function sayColor(){
  alert(this.color)
}
var objectSayColor = sayColor.bind(o);
objectSayColor();//blue

补充说明:执行环境定义
定义了变量或者函数有权访问的其他数据,每个执行环境都有一个与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。我们编写的代码无法访问这个对象,但解析器会在处理数据时在后台使用它。
一、执行环境的创建:

1.全局执行环境
在web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。代码载入浏览器时,全局执行环境被创建(当我们关闭网页或者浏览器时全局执行环境才被销毁)。

2.局部执行环境
每个函数都有自己的执行环境,因此局部执行环境为函数对象。当函数被调用时函数的局部环境被创建(函数内的代码执行完毕后,该环境被销毁,同时保存在其中的所有变量和函数定义也随之被销毁)。

这个执行环境以及相关的变量对象是个抽象的概念,解释如下

var a = 1;
function fn(num1,num2){
  var b = 2;
  function fnInner(){
    var c = 3;
    alert(a + b + c);
  }
  fnInner();//fnInner调用时局部执行环境创建
}
fn(4,5);//fn调用时局部执行环境创建

二、作用域链
javascript函数的执行用到了作用域链,这个作用域链是函数定义的时候创建的,当定义一个函数时,它实际保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的作用域链。作用域链的前端始终都是当前执行的代码所在环境的变量对象。作用域链的末端始终都是全局执行环境的变量对象。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有权访问

var scope = 'global scope';
function checkscope(){
  var scope = 'local scope';
  function f(){return scope};
  return f;
}
checkscope()();//local scope

理解:当调用checkscope时,函数f被定义并作为局部变量绑定到了checkscope作用域链上,因此函数f无论在哪里调用,这种绑定依然有效,因此返回值为local scope。

var num1 = 1;
function Outer(){
  var num2 = 2;
  console.log(num1 + num2);//3
  function Inner(){
    //这里可以访问num3,num2,num1
    var num3 = 3;
    console.log(num1 + num2 + num3);//6
    }
  //这里可以访问num2,Inner(),num1但不能访问num3
  Inner();
}
Outer();
console.log(num1);//1,执行环境
//这里只能访问num1

作用域链(向上搜索):内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。

 var name = 'Byron';
  function fn(){
    var name = 'Csper';
    console.log(name);//Casper
  }
  fn();

越往内部的环境,变量权重越高。

注意:没有带var关键字直接声明的变量属于全局变量如直接声明a = 1,此时的a为全局变量。

javscript引擎在进入作用域时,会对代码分两轮处理。第一轮,初始化变量。第二轮,执行代码

var a = 1;
function prison (a) {
  console.log(a);//1
  var a;
  console.log(a);//1
}
prison(1);

三、函数执行
函数调用进入执行环境时,首先处理arguments,初始化形参(默认值为undefined),然后初始化函数内的函数声明,当代码一步一步执行时再初始化函数内的变量声明(进入环境未开始执行代码时,值为undefined)。所以函数内的初始化顺序为形参,函数声明,变量声明。可以从上图图一看出。下面我来举个例子(整个全局环境也是函数)。

alert(typeof fn);//function,函数声明提前
alert(typeof fn0);//undefined,变量声明提前但未赋值
function fn(){
//函数表达式
}
var fn0 = function(){
//函数定义式
}
alert(typeof fn0);//function,此时变量已被赋值
(0)

相关推荐

  • 再次谈论Javascript中的this

    一直对Javascript中的this都有一种似是而非的感觉,今天突然感觉豁然开朗,特此记录一下. 咱们先看个栗子: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this的使用</title> <script type="text/javascript"> var Car,tesla; Car=functio

  • JavaScript中的this使用详解

    其实this是一个老生常谈的问题了.关于this的文章非常多,其实我本以为自己早弄明白了它,不过昨天在做项目的过程中,还是出现了一丝疑惑,想到大概之前在JavaScript weekly里收藏待看的一篇详解this的文章(后有链接,也附上了稀土上的中文译文)和另一篇一位前辈推荐的文章,就把它们看了看,对this的认识确实提升了一些. JavaScript 中的'this'是动态的,它在函数运行时被确定而非在函数声明时被确定.所有的函数都可以调用'this',这无关于该函数是否属于某个对象.关于t

  • js老生常谈之this,constructor ,prototype全面解析

    前言 javascript中的this,constructor ,prototype,都是老生常谈的问题,深入理解他们的含义至关重要.在这里,我们再来复习一下吧,温故而知新! this this表示当前对象,如果在全局作用范围内使用this,则指代当前页面对象window: 如果在函数中使用this,则this指代什么是根据运行时此函数在什么对象上被调用. 我们还可以使用apply和call两个全局方法来改变函数中this的具体指向. 先看一个在全局作用范围内使用this的例子: console

  • JavaScript知识点总结(十)之this关键字

    this是Javascript语言的一个关键字.随着函数使用场合的不同,this的值会发生变化.但是有一个总的原则,那就是this指的是,调用函数的那个对象.JavaScript中的this指针是一个动态的变量,一个方法内的this指针并不是始终指向定义该方法的对象的.Javascript中this关键字通常指向当前函数的拥有者. 下面通过代码给大家介绍下.具体代码如下所示: <script type="text/javascript"> function Person()

  • tomcat6下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法

    1.在tomcat6.0下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法 在tomcat6.0下jsp中出现此错误一般都是在jsp中使用了输出流(如输出图片验证码,文件下载等),没有妥善处理好的原因. 具体的原因就是: 在tomcat中jsp编译成servlet之后在函数_jspService(HttpServletRequest request, HttpServletResponse res

  • javascript this详细介绍

    this的值是在运行时确定的 JS中的this究竟代表什么,这是在程序运行时根据上下文环境确定,可以分为以下几种情况. 1. 全局作用域中的this 在全局作用域中,this指向window对象. console.log(this);//指向window对象 this.x = 5//在全局作用域内创建一个x //与this.x = 5的等价情况: //var x = 5; //x = 5; 在全局作用域中执行var x=5,其实是为window对象创建一个属性x,并令其等于5. 若定义变量时不加

  • 聊一聊JS中this的指向问题

    JS中的this指向一直是个让人头疼的问题,想当初我学的是天昏地暗,查了好多资料,看的头都大了,跟他大战了那么多回合,终于把它搞定个七八分,其实往往都是我们复杂化了,现在就让大家轻松看懂this的指向,我会分以下几种情况来说. this的指向: 1.this 指的是调用当前方法(函数)的那个对象,也就是说函数在谁那被调用,this就指的是谁. 来看两个栗子: oBtn.onclick = function(){ alert(this); //oBtn } oBtn[i].onclick = fn

  • javascript中this指向详解

    JavaScript 是一种脚本语言,支持函数式编程.闭包.基于原型的继承等高级功能.JavaScript一开始看起来感觉会很容易入门,但是随着使用的深入,你会发JavaScript其实很难掌握,有些基本概念让人匪夷所思.其中JavaScript 中的 this 关键字,就是一个比较容易混乱的概念,在不同的场景下,this会化身不同的对象.有一种观点认为,只有正确掌握了 JavaScript 中的 this 关键字,才算是迈入了 JavaScript 这门语言的门槛.在主流的面向对象的语言中(例

  • 学习掌握JavaScript中this的使用技巧

    tip 首先,我知道这篇文章很无聊,无非就是关于 js 中的 this,并且也已经有千千万万的文章写过这部分内容了:  但是,我还是想写一篇关于 js 中的 this 的文章,算是一个总结归纳吧:(大神们可以绕行看我的其他文章)  在 js 中,this 这个上下文总是变化莫测,很多时候出现 bug 总是一头雾水,其实,只要分清楚不同的情况下如何执行就 ok 了. 全局执行 首先,我们在全局环境中看看它的 this 是什么:  first. 浏览器: console.log(this); //

  • 老生常谈 js中this的指向

    在js中this的指向对于新手来说一定是个难题,但是如果你真正理解了的话,也就没什么问题啦,下面就来讲讲this吧. JS中,this的值取决于调用的模式(调用对象),而JS中共有4种调用模式: 1.函数调用模式 当一个函数不是一个对象的属性时,当作函数俩调用,这时函数内的this指向全局对象(大对数情况下是window) window.value=1; function getValue(){ console.log(this.value); } getValue();//输出1,此时的thi

随机推荐