JS、Vue中的this指向 + 使用apply()、call()、bind()方法修改this指向_vue点击事件绑定this_emmmmimport的博客-CSDN博客

目录

前言

一、JS中五种情形下的this指向:

1.函数

2.方法

3.构造函数

4.响应函数

5.修改指向时

二、Vue 项目中三种情形下的this指向:

1.被Vue所管理的普通函数

2.不被Vue所管理的函数

3.其他情况

注意:

三、使用apply()、call()、bind()方法修改this指向:

注意:

1. apply()

2. call()

3. bind()

    • *

前言

        浏览器在调用函数时,每次都会向函数内部传递一些隐含的参数,this就是其中之一,this的指向是函数执行的上下文对象,而当函数的调用方式不同时,this所指向的这个上下文对象也是不一样的,常见的具体情况如下。

    • *

一、JS中五种情形下的this指向:

1.函数

        当以函数的形式调用时,this指向_ 全局对象window _:

function test() {  console.log(this)}//输出内容(全局对象window):Window {window: Window, self: Window, document: document, name: '', location: Location, …}test()

2.方法

        当以方法的形式调用时,this指向 该方法的调用者

var obj = {  //当对象的一个属性为函数时,称这个函数为该对象的方法  test: function() {    console.log(this)  }}//输出内容(对象obj):{test: ƒ}obj.test()

3.构造函数

        当以构造函数的形式调用时,this指向 新创建的那个对象

function Test() {  //使用二元运算符instanceof来验证此时的这个this是Test()类的实例,即该构造函数创建出的新对象  console.log(this , this instanceof Test)    }//输出内容(分别为新对象demo和布尔值true):Test {}    truevar demo = new Test()

4.响应函数

        在事件的响应函数中,this指向 响应函数的绑定者

<button id = 'btn'>  点我输出this</button>
var btn = document.getElementById('btn')//给按钮btn绑定一个点击事件btn.onclick = function() {  console.log(this)}//点击按钮后的输出内容(按钮btn):<button id = 'btn'> 点我输出this </button>

5.修改指向时

        使用apply()、call()、bind()方法改变this指向时,this的指向就是 _方法中所指定的那个对象_(详细示例见第三部分)。

    • *

二、Vue 项目中三种情形下的this指向:

1.被Vue所管理的普通函数

        被Vue所管理的函数为普通函数时(如 methods computed watch 等配置项中的函数是普通函数的形式时),其this指向 Vue的实例对象vm或组件实例对象vc(以后者为例):

//此为组件HelloWorld.vue内容:<template>  <div class="hello">    <button @click="test()">点我输出this</button>  </div></template> <script>export default {  name: "HelloWorld",//举methods中的普通函数为例  methods: {    test() {      console.log(this)    }  },};</script>//点击按钮后输出内容为(组件实例对象vc):VueComponent {_uid: 5, _isVue: true, __v_skip: true, _scope: EffectScope, $options: {…}, …}

2.不被Vue所管理的函数

        不被Vue所管理的函数若为箭头函数时(当methods、computed、watch等配置项中的定时器回调函数、ajax的回调函数都写为箭头函数的形式时),由于箭头函数的this总是指向词法作用域,即外层调用者,所以此时其this同样指向 Vue的实例对象vm或组件实例对象vc(以后者为例):

//以下为组件HelloWorld.vue的内容:<template>  <div class="hello">    <button @click="test()">点我输出this</button>  </div></template> <script>export default {  name: "HelloWorld",  methods: {    test() {      //开启定时器      setTimeout(()=> {        console.log(this);      }, 200);    },  },};</script> <style scoped></style>//点击按钮200ms后输出内容为(组件实例对象vc):VueComponent {_uid: 2, _isVue: true, __v_skip: true, _scope: EffectScope, $options: {…}, …}

3.其他情况

        在 组件的自定义事件(下面的代码以此为例)、全局事件总线消息订阅与发布 中,若其回调函数配置在methods中(见注释写法一),或是其回调函数为箭头函数(见注释写法二),则该回调函数的this指向也是 _Vue的实例对象vm或组件实例对象vc_(以后者为例):

//以组件的自定义事件为例,以下是App.vue的内容:<template>  <div id="app">    <HelloWorld ref="demo"/>  </div></template> <script>import HelloWorld from './components/HelloWorld.vue' export default {  name: 'App',  components: {    HelloWorld,  },  //写法一:将事件回调放在methods中  methods:{    test() {      //输出内容(组件实例对象vc):VueComponent {_uid: 1, _isVue: true, __v_skip: true, _scope: EffectScope, $options: {…}, …}      console.log(this)    }  },  mounted() {    this.$refs.demo.$on('showThis',this.test)  }   //写法二:将事件回调写在mounted中,使用箭头函数的写法,不写methods中的test()方法  mounted() {    //输出内容(组件实例对象vc):VueComponent {_uid: 1, _isVue: true, __v_skip: true, _scope: EffectScope, $options: {…}, …}    this.$refs.demo.$on('showThis', () => console.log(this))  }}</script>
//以下是HelloWorld.vue的内容:<template>  <div class="hello">    <button @click="emitShowThis()">点我触发showThis事件</button>  </div></template> <script>export default {  name: "HelloWorld",  methods: {    emitShowThis() {      //触发showThis事件      this.$emit('showThis')      //解绑showThis事件(若在此时解绑,则点击按钮总共只进行一次输出)      this.$off('showThis')    }  },};</script>

注意:

这种情况不多,因为 Vuex 可以替代组件的自定义事件、全局事件总线、消息订阅与发布,如会使用Vuex,则此种情况可以忽略。

另外,将上述三种情况分别反过来,则this的指向将不再为Vue的实例对象vm或组件实例对象vc_,_此时this指向 需要具体分析

    • *

三、使用apply()、call()、bind()方法修改this指向:

注意:

值得注意的是,虽然这三种方法都可以改变this的指向,但在使用时也稍有区别:

(1)在调用apply()或call()时,都会直接调用函数执行,但在调用bind()时,就不会调用函数执行,而是会返回一个this指向被修改好的新函数供我们调用。

(2)在传参时,第一个参数就是需要让this去指向的对象,若还有其他参数,在使用apply()时,需要将第二个及以后的参数封装到同一个数组中进行传递;在使用call()时,只需要将其他参数依次在第一个参数之后传递即可;在使用bind()时,第二个及以后的参数需要在新函数中传,传递方式同call()一样,无需封装。

_修改示例 _具体如下(第一部分中第2种情况下的this指向应为对象obj,现将其修改为window):

1. apply()

        使用apply()方法修改this指向:

var obj = {  test: function (val) {    console.log(val, this)  }}//输出内容(100和window):100    Window {window: Window, self: Window, document: document, name: '', location: Location, …}obj.test.apply(window, [100])

2. call()

        使用call()方法修改this指向:

var obj = {  test: function (val) {    console.log(val, this)  }}//输出内容(200和window):200    Window {window: Window, self: Window, document: document, name: '', location: Location, …}obj.test.call(window, 200)

3. bind()

        使用bind()方法修改this指向:

var obj = {  test: function (val) {    console.log(val, this)  }}//输出内容(300和window):300    Window {window: Window, self: Window, document: document, name: '', location: Location, …}var demo = obj.test.bind(window)demo(300)

原网址: 访问
创建于: 2023-08-07 17:05:34
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论