JavaScript中的this

7次阅读

共计 2670 个字符,预计需要花费 7 分钟才能阅读完成。

1:基本概念

this 字面意思是当前,当前执行代码的环境对象或者是上下文。代表着当前方法执行的环境上下文,那么何为环境上下文,通俗的说,谁调用了函数,谁就是这个函数的环境上下文。

在 js 中,this 只有两种指向,一种是指向当前的封闭作用域,或者是指向当前作用域的外层,this 的最顶层就是 window 对象。

关于 this 必须要了解的是严格模式,严格模式是 js 里面的一个子集,是具有限制性 JavaScript 变体,严格模式也是 js 的一种,但是加了一些限制。

比如:

  • 在严格模式下通过抛出错误来消除了一些原有的静默错误(静默错误:语法有错误但是 js 并没有提示,默认允许这个操作)。比如要取一个函数的传入参数,在非严格模式下,可以直接拿到它的 grument,但在严格模式下会抛出一个错误。
  • 严格模式修复了一些导致 JavaScript 引擎难以执行优化的缺陷
  • 禁用了在 ECMAScript 的未来版本中可能会定义的一些语法

进入 ” 严格模式 ” 的标志:”use strict”;

    // 为整个脚本开启严格模式 
    "use strict";
    var v = "Hi!  I'm a strict mode script!";
    
    // 为函数开启严格模式 
    function strict() {
        'use strict';
        function nested() {return "And so am I!";}
        return "Hi!  I'm a strict mode function!  " + nested();}

2:全局环境

在全局环境下,无论是否在严格模式下,在全局执行环境下(任何函数体外部)this 指向全局对象。也就是说在全局执行环境,这个 this 永远指向全局对象,这个全局对象在浏览器中就是 window。

    // 浏览器环境
    var name = 'Eric';
    console.log(window.name === this.name);  /* true */
    console.log(window === this);            /* true */

3:函数体内部

在函数体内部,this 的值取决于函数被调用的方式。函数被调用的方式有很多种:

简单调用,也就是说没有添加任何额外的操作,没有添加一个 this 的绑定或者是改变。

简单调用分为严格模式与非严格模式。

  • 在非严格模式下,this 默认指向全局对象。

      // 浏览器环境
      function simple(){return this;}
      console.log(simple() === window);
      // true
  • 在严格模式下,保持进入执行环境时的值,没有指定时默认 undefined。

      // 浏览器环境
      function simple2(){
          "use strict";
          return this;
      }
      simple2() === undefined;
      // true 
      window.simple2() === window;
      // true 

this 传递,在 js 中 this 绑定有两种:

  • 一种是 call/apply,可以看作是一种,它们都是一个绑定 this 的立即执行的一个方法,绑定之后会立即执行这个函数,两者的区别在于传递参数的不同,一个是传一个参数,一个是传一堆参数;call/apply 实际上是绑定值的是一个对象,存在一个 ToObject 过程。call/apply 是一个立即执行的绑定 this 的一个操作。

      // 浏览器环境 
      var object = {name: 'Eric'};
      var name = 'Iven';
      function getName(arg) {return this.name;}
      
      getName(); /* Iven */
      getName.call(object); /* Eric */
      getName.apply(object); /* Eric */
  • 另一种是 bind,与上面不同的是 bind 不会立即执行,它只是实现一个绑定的过程,返回的是一个柯里化的函数,这个柯里化的函数就是 call/apply。bind 只能被绑定一次。

      name = 'Davy';
      function bindThis(){return this.name;}
      var getName1 = bindThis.bind({name: "Eric"});
      console.log(getName1()); /* Eric */
      
      var getName2 = getName1.bind({name: "Iven"});
      console.log(getName2()); /* Eric */

箭头函数 在执行的时候会形成一个封闭的作用域,this 与封闭作用域的 this 保持一致,call/apply/bind 都将会被忽略。

// 浏览器环境 
var globalThis = this;
var arrowsFunction = () => this;
console.log(arrowsFunction() === globalObject); /* true */

作为对象的方法被调用(有一个靠近原则):在对象里面定义了一个函数,然后通过对象去调用这个函数。

// 浏览器环境 
var object = {
    name: 'Eric',

    getName: function() {return this.name;}
};
console.log(object.getName()); /* Eric */


function getName2() {return this.name;}
object.getName = getName2;
console.log(object.getName()); /* Eric */


object.object = {
    getName: getName2,
    name: 'Iven'
};
console.log(object.object.getName()); /* Iven */

4:全局函数

  • setTimeout
  • setInterval
  • alert

setInterval()方法用于在指定的毫秒数后调用函数或计算表达式。

语法:setTimeout(code,millisec),参数 code 必需,要调用的函数后执行的 JavaScript 代码串;millisec 必需,在执行代码前等待的毫秒数。

注意 :setTimeout() 只执行 code 一次,如果需要多次调用,请使用 setInterval()或者让 code 自身再次调用 setTimeout(),也就是利用递归。

setInterval()方法可按照指定的周期来调用函数或计算表达式。它会不停地调用函数,指导 clearInterval()被调用或者窗口被关闭。由 setInterval()返回的 ID 值可以用作 clearInterval()方法的参数。

语法:setInterval(code,millisec[,"lang"])

正文完
 0

JavaScript中的this

7次阅读

共计 1913 个字符,预计需要花费 5 分钟才能阅读完成。

JS JavaScript 中的 this

this 是 JavaScript 语言中的一个关键字它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。
function test() {
this.x = 1;
}
那么,this 的值是什么呢?函数在不同使用场合,this 有不同的值。总之,this 就是函数运行时所在的环境对象。
情况一:纯粹的函数调用
这是函数的最常通用法,属于全局性调用,因此 this 就代表全局对象。
var x = 1;
function test() {
console.log(this.x);
}
test(); // 1
情况二:作为对象的方法调用
函数还可以作为某个对象的方法调用,这时 this 就指这个上级对象
function test() {
console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1
情况三:作为构造函数调用
构造函数就是通过这个函数可以生成一个新对象。这时,this 就指这个新对象
function test() {
this.x = 1;
}

var obj = new test();
obj.x // 1
为了表明这时 this 不是全局对象,下面代码:
var x = 2;
function test() {
this.x = 1;
}

var obj = new test();
x // 2
运行结果为 2,表明全局变量 x 的值没有变化
情况四:apply 调用

apply() 是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时 this 指的就是这个参数。
var x = 0;
function test() {
console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply() // 0
apply() 的参数为空时,默认调用全局变量。因此,这时运行结果为 0,证明 this 指的是全局对象。如果把最后一行代码修改成
obj.m.apply(obj); //1
运行结果就变成 1,证明这时 this 代表的对象是 obj
改变 this 的指向有以下几种方法

使用 ES6 的箭头函数
在函数内部_this=this

使用 apply、call、bind

new 实例化一个对象

其实 this 的指向,始终坚持一个原理:this 永远指向最后调用它的那个对象。
例 1:
var name = “windowsName”;
function a() {
var name = “Cherry”;

console.log(this.name); // windowsName

console.log(“inner:” + this); // inner: Window
}
a();
console.log(“outer:” + this) // outer: Window
这里我们使用严格模式,如果使用严格模式的话,全局对象就是 undefined,那么就会报错 Uncaught TypeError: Cannot read property ‘name’ of undefined。
例 2:
var name = “windowsName”;
var a = {
name: “Cherry”,
fn : function () {
console.log(this.name); // Cherry
}
}
a.fn();
例 3:
var name = “windowsName”;
var a = {
name: “Cherry”,
fn : function () {
console.log(this.name); // Cherry
}
}
window.a.fn();
例 4:
var name = “windowsName”;
var a = {
// name: “Cherry”,
fn : function () {
console.log(this.name); // undefined
}
}
window.a.fn();
例 5:
var name = “windowsName”;
var a = {
name : null,
// name: “Cherry”,
fn : function () {
console.log(this.name); // windowsName
}
}

var f = a.fn;
f();
为什么不是 Cherry,这是因为虽然将 a 对象的 fn 方法赋值给变量 f 了,“this 永远指向最后调用它的那个对象”,由于刚刚的 f 并没有调用,所以 fn() 最后仍然是被 window 调用的。所以 this 指向的也就是 window。
例 6:
var name = “windowsName”;

function fn() {
var name = ‘Cherry’;
innerFunction();
function innerFunction() {
console.log(this.name); // windowsName
}
}

fn()

正文完
 0