设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 3332|回复: 7
打印 上一主题 下一主题

[原创发布] 简明易懂的this指针, call, apply 和 bind教程

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1912
在线时间
1554 小时
注册时间
2013-4-13
帖子
917
跳转到指定楼层
1
发表于 2016-6-16 20:14:18 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 沉滞的剑 于 2017-8-3 12:53 编辑

依然是帮助新学JS的新人快速上手的简单教程.
和之前的教程一样是帮助大家阅读和模仿MV的源码而普及的基础知识
这是对修改甚至自己写脚本需要迈出的第一步.

1. this指针
this是一个指针,指向一个对象,在通常情况下它指的是代码的所有者.更正应该是呼叫者
例子1:
JAVASCRIPT 代码复制
  1. console.log(this)

返回:Window
结论:Window是所有全局代码的呼叫者.
例子2:
JAVASCRIPT 代码复制
  1. function a(){
  2. function b(){
  3.   console.log(this)
  4. }
  5. console.log(this)
  6. b();
  7. }
  8. a();

返回:Window, Window
例子3:
JAVASCRIPT 代码复制
  1. a = {};
  2. a.b = function(){console.log(this)}
  3. c = [];
  4. c[0] = function(){console.log(this)}
  5. a.b();
  6. c[0]();

返回:Object{....}和Array[...]
结论:通过上面的2个例子可以看出呼叫者是通过.或[]的语法关系体现的而和{}的层级无关.更正:呼叫者和被呼叫者的关系和被呼叫的函数所声明的位置无关,之和呼叫的主体有关。
例子4:
JAVASCRIPT 代码复制
  1. function a(){
  2. console.log(this)
  3. }
  4. b = {};
  5. b.c = a;
  6. b.c();

返回:Object{...}
结论: this和函数声明所在的{}层级无关, 只和对象的层级有关和上面的结论一致.

总结: this指针的指向判断要根据上下文, 也就是代码的所有者, 调用者. 注意看.和[]来判断从属关系.
2.call, apply 和 bind
以上讨论的仅是一般情况.
作为动态语言, js支持更改this指针的上下文, 也就是说改变this的指向.
最常用的就是call函数
call函数的作用是替换this指针, 立刻呼叫这个函数
call函数的格式如下
Function.prototype.call(this指针指向的对象,  函数的参数1, 函数的参数2......)
例子1:
JAVASCRIPT 代码复制
  1. function a(){
  2. console.log(this.e);
  3. }
  4. b = {};
  5. b.c = a;
  6. b.e = 'B';
  7. d = {}
  8. d.e = 'D'
  9. b.c.call(d);

输出: 'D'
结论: call函数改变了this指针的指向
apply函数和call函数是等价的, 只是参数上有少许变化:
Function.prototype.apply(this指针指向的对象,  [函数的参数1, 函数的参数2......])
例子2:
JAVASCRIPT 代码复制
  1. function a(){
  2. console.log(this.e);
  3. }
  4. b = {};
  5. b.c = a;
  6. b.e = 'B';
  7. d = {}
  8. d.e = 'D'
  9. b.c.apply(d);

输出:'D'
结论: apply除了把参数用一个数组包起来以外...嗯...基本和call没区别.
bind也是用来改变this上下文的, 和call格式上很像
Function.prototype.bind(this指针指向的对象,  [函数的参数1, 函数的参数2......])
但是有一点很重要, bind并不是执行函数, 而是返回函数对象.
也就是说bind本身不会执行函数, 它返回了一个修改过this指针的新函数.
例子3:
JAVASCRIPT 代码复制
  1. function a(){
  2. console.log(this.e);
  3. }
  4. b = {};
  5. b.c = a;
  6. b.e = 'B';
  7. d = {}
  8. d.e = 'D'
  9. f = b.c.bind(d);
  10. f();

输出:'D'
结论: bind和call或apply不同, 并不会直接执行函数而是返回了一个修改过this指针指向的新函数.
接下来展示几个带参数的用法.
例子4:
JAVASCRIPT 代码复制
  1. a = {};
  2. b = {};
  3. c = function(str, num){
  4. console.log(this.e);
  5. console.log(str + ':' + (++num));
  6. }
  7. a.e = 'A'
  8. b.e = 'B'
  9. a.d = c;
  10. a.d.call(b,'HeartCase',3)
  11. a.d.apply(b,['HeartCase',3])
  12. a.d.bind(b,'HeartCase',3)();

输出:B, HeartCase:4,B, HeartCase:4,B, HeartCase:4
结论: 以上三种写法是等价的
关于call, apply 和 bind使用的奇技淫巧是很多的
对于想要了解js原理的人来说, 对这三个函数的掌握是非常重要的,它们也有很多高级进阶技巧
但是对我们这些基础的使用者,至少对RM来说保持良好的可读性才是第一位的
弄懂了这些, 帮助你阅读源码是十分有利的.

总结:
this指针指向的是代码的所有者
利用call, bind 和 apply可以修改this指针的指向


其他: js中还有一个蛋疼的东西叫原型和原型链, 我觉得我也有必要向新手普及一下
因为需要很多配图所以不知道猴年马月能更新...
(这个月不就是猴年马月么!!!)

评分

参与人数 2星屑 +32 收起 理由
79160475 + 26 精品文章
沧笙 + 6 精品文章

查看全部评分

夏普的道具店

塞露提亚-道具屋的经营妙方同人作品
发布帖:点击这里

Lv1.梦旅人

梦石
0
星屑
186
在线时间
25 小时
注册时间
2024-1-25
帖子
5
5
发表于 2024-4-5 10:58:05 | 只看该作者
当函数作为构造函数被调用(new操作符)时,this指向命名的对象实例;不是作为构造函数被调用时(直接被调用),this由运行时的对象上下文决定,在window全局对象下调用就指向window,作为对象的方法被调用时,this指向该对象。
青山依旧在,几度夕阳红。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
55
在线时间
69 小时
注册时间
2008-3-2
帖子
29
4
发表于 2016-10-6 18:45:11 | 只看该作者
this,代码的所有者。这样看是很好理解,但是在实际插件中,就好昏,不知道this到底指的是什么东西。

点评

通常都在函数第一行写上var context=this;固定住引用目标  发表于 2016-10-6 19:55
this最常用的地方就是书写原型链构成的类时,在成员函数的调用中,作为当前的类实例的引用,不过由于坑爹的作用域变换(大雾)  发表于 2016-10-6 19:55
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

3
发表于 2016-6-17 21:41:56 | 只看该作者
本帖最后由 taroxd 于 2016-6-21 11:44 编辑

js 的 this 就是个神奇的东西,不需要去花太多时间搞得很清楚。有了 arrow function 之后 this 才算稍微正常一点。

特别是第一点和第二点,因为安全问题已经不建议使用了。(在 strict mode 里面,允许 this 为 undefined)

JAVASCRIPT 代码复制
  1. function foo() {
  2.   'use strict'
  3.   console.log(this)
  4. }
  5.  
  6. class C {
  7.   bar() {
  8.     console.log(this)
  9.   }
  10. }
  11.  
  12. foo()  // undefined, NOT Window
  13. let {bar} = C.prototype
  14. bar()  // undefined, NOT Window


另外,js 没有规定全局对象叫 window。node 里面就叫 global
为啥要吐槽这个?因为我写js主要就是node环境

点评

“不要搞得太清楚比较好”好评233  发表于 2016-6-17 22:00
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
73 小时
注册时间
2016-4-6
帖子
39
2
发表于 2016-6-17 16:20:19 | 只看该作者
這裡有其中一個受惠的新手 等著更新
這篇文  不是寫給空氣看哦
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-23 08:35

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表