讨论:JS你阅览无数,但你知道this在其中所扮演的角色吗?

this第一奥义:

  • 对于许多刚刚接触前端的学者来说,this时常出现在编程中。虽然知道this用途的强大,但对于提示的作用并不是过于了解,而今天就让Damon跟大家说说this在JS中能够扮演的角色。
前提先知:
  • 对于在开始讲解this之间我们需要知道,从java或者是从PHP等标准语言对于this的看法来说。大多数情况下,虽说this能够使用的场景有许多,但是this作为表示类方法中的当前对象的实例,是无法使用在方法之外进行使用。

  • 函数调用:执行构成函数主体的代码:例如,parseInt函数调用是’’‘parseInt(‘15’)’’’。

  • 调用的上下文:指 this 在函数体内的值。例如,’’'map.set(‘key’, ‘value’)的调用上下文是 map。

  • 函数的作用域:是指在函数体中可访问的变量、对象和函数的集合。

JS调用方式:

  • 在就是中使用this的情况就与前文所的有所不同,this在这更多是表示函数当前执行上下文,而在js调用函数时常是用一下这些方法:
    • 函数的调用:alert('Hello World!')
    • 方法的调用:console.log('Hello World!')
    • 方法的调用:```console.log(‘Hello World!’) ``````
    • 隐式调用: alert.call(undefined, ‘Hello World!’) ```
  • 对于以上的调用方式,每种调用类型以自己的方式定义上下文,所以在日常编程中也是容易出现混淆的情况。另外一点就是在严格模式中,调用函数会出现影响上下文的情况。

函数调用角色

  • 首先,在我们日常编辑的时候,当一个表达式为函数接着一个(,一些用逗号分隔的参数以及一个)时,函数调用被执行。在这里我们从日常的比如parseInt(‘18’)能够看出。

  • 但是我们也是知道函数调用表达式不能是属性方式的调用,如 obj.myFunc(),这种是创建一个方法调用。再如 [1,5].join(’,’)不是函数调用,而是方法调用,这种区别需要记住哈,很重要滴。

    • 下面给大家举一个调用的例子:
    • function hello(name) {
      return 'Hello ’ + name + ‘!’;
      }
      // 函数调用
      const message = hello(‘World’);
      console.log(message); // => ‘Hello World!’
    • 在这里我们可以看到,hello(‘World’)是函数调用: hello表达式等价于一个函数,跟在它后面的是一对括号以及’World’参数。

在函数调用中的this扮演什么角色?

  • this 在函数调用中是一个全局对象,局对象由执行环境决定。在浏览器中,this是 window 对象。在函数调用中,执行上下文是全局对象。

    接下来我们通过案例来看下:

      function sum(a, b) {
         console.log(this === window); // => true
         this.myNumber = 20; // 将'myNumber'属性添加到全局对象
         return a + b;
      }
      // sum() is invoked as a function
      // sum() 中的 `this` 是一个全局对象(window)
      sum(15, 16);     // => 31
      window.myNumber; // => 20
    
    • 在调用sum(15,16)时,JS 自动将this设置为全局对象,在浏览器中该对象是window。当this在任何函数作用域(最顶层作用域:全局执行上下文)之外使用,this 表示 window 对象

       console.log(this === window); // => true
       this.myString = 'Hello World!';
       console.log(window.myString); // => 'Hello World!'
      
       <!-- In an html file -->
       <script type="text/javascript">
          console.log(this === window); // => true
       </script>
      

严格模式下的函数调用 this 扮演什么角色?

  • this 在严格模式下的函数调用中为 undefined。严格模式是在 ECMAScript 5.1中引入的,它提供了更好的安全性和更强的错误检查。要启用严格模式,函数头部写入use strict 即可。启用后,严格模式会影响执行上下文,this 在常规函数调用中值为undefined。与上述情况2.1相反,执行上下文不再是全局对象。

  • 下面战士下严格模式函数调用示例:

      	function multiply(a, b) {
      	  'use strict'; // 启用严格模式
      	  console.log(this === undefined); // => true
      	  return a * b;
      	}
      	multiply(2, 5); // => 10
    
  • 当multiply(2,5)作为函数调用时,this是undefined。严格模式不仅在当前作用域中有效,在内部作用域中也是有效的(对于在内部声明的所有函数):

      function execute() {
         'use strict'; // 开启严格模式  
         function concat(str1, str2) {
      	 // 严格模式仍然有效  
      	 console.log(this === undefined); // => true
      	 return str1 + str2;
         }
         // concat() 在严格模式下作为函数调用
         // this in concat() is undefined
         concat('Hello', ' World!'); // => "Hello World!"
      }
      execute();
    
  • 'use strict’被插入到执行体的顶部,在其作用域内启用严格模式。因为函数concat是在执行的作用域中声明的,所以它继承了严格模式。单个JS文件可能包含严格和非严格模式。因此,对于相同的调用类型,可以在单个脚本中具有不同的上下文行为:

      function nonStrictSum(a, b) {
        // 非严格模式
        console.log(this === window); // => true
        return a + b;
      }
      function strictSum(a, b) {
        'use strict';
        // 启用严格模式
        console.log(this === undefined); // => true
        return a + b;
      }
    
      nonStrictSum(5, 6); // => 11
      strictSum(8, 12); // => 20
    

方法调用中 this 扮演什么角色?

  • 在方法调用中,this是拥有这个方法的对象。当调用对象上的方法时,this就变成了对象本身。
    -在这里我们来看个案例:首先创建一个对象,该对象有一个递增数字的方法

      const calc = {
        num: 0,
        increment: function() {
      	console.log(this === calc); // => true
      	this.num += 1;
      	return this.num;
        }
      };
      // method invocation. this is calc
      calc.increment(); // => 1
      calc.increment(); // => 2
    
  • 调用calc.increment()使increment函数的上下文成为calc对象。所以使用this.num来增加num属性是有效的。再来看看另一个例子。JS对象从原型继承一个方法,当在对象上调用继承的方法时,调用的上下文仍然是对象本身

     const myDog = Object.create({
       sayName: function() {
     	 console.log(this === myDog); // => true
     	 return this.name;
       }
     });
     myDog.name = 'Milo';
     // 方法调用 this 指向 myDog
     myDog.sayName(); // => 'Milo'
    
  • Object.create()创建一个新对象myDog,并根据第一个参数设置其原型。myDog对象继承sayName方法。执行myDog. sayname()时,myDog是调用的上下文。在EC6 class 语法中,方法调用上下文也是实例本身

      class Planet {
        constructor(name) {
      	this.name = name;    
        }
        getName() {
      	console.log(this === earth); // => true
      	return this.name;
        }
      }
      var earth = new Planet('Earth');
      // method invocation. the context is earth
      earth.getName(); // => 'Earth'
    

构造函数中的 this所扮演的角色

  • 在构造函数调用中 this 指向新创建的对象。构造函数调用的上下文是新创建的对象。它利用构造函数的参数初始化新的对象,设定属性的初始值,添加事件处理函数等等。

  • 来看看下面示例中的上下文
    function Foo () {
    console.log(this instanceof Foo); // => true
    this.property = ‘Default Value’;
    }
    // Constructor invocation
    const fooInstance = new Foo();
    fooInstance.property; // => ‘Default Value’

  • new Foo() 正在进行构造函数调用,其中上下文是fooInstance。在Foo内部初始化对象:this.property被赋值为默认值。同样的情况在用class语法(从ES6起)时也会发生,唯一的区别是初始化在constructor方法中进行:

      class Bar {
        constructor() {
      	console.log(this instanceof Bar); // => true
      	this.property = 'Default Value';
        }
      }
      // Constructor invocation
      const barInstance = new Bar();
      barInstance.property; // => 'Default Value'
    

总结:

作为一个新生程序猿,Damon希望能够与大家一同进步。文章或者描述有所不足的地方,希望大家多多提出来,一同进步。
Damon会继续发掘一些有用的咨询,知识以及新工具,与大家一同分享,谢谢!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值