this与bind(this)

this

this指向的是当前函数的作用域(对象实例),有如下的例子

const app = {
name: 'xiaoming',
log() {
console.log(this.name);
},
child() {
return {
name: 'b',
log() {
console.log(this.name);
},
};
},
};
app.log(); // xiaoming
app.child().log(); // b

this详细

- 全局环境

无论是否在严格模式(‘use strict’)下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。

console.log(this === window); // true

this.name = 'react';
console.log(name); // react
console.log(window.name); // react

- 函数内

在函数内部,this的值取决于函数被调用的方式。

1. 普通函数

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

function f() {
return this;
} // brower
f() === window;
// node
f() === global;

严格模式下,this默认指向调用函数的对象实例。

function f() {
'use strict'
return this;
}
f() === undefined;
因为这里的f()是直接调用的,而不是作为对象的属性或方法调用的,如window.f(),所以这里的this为undefined。

如果要想把 this 的值从一个环境传到另一个,就要用 call 或者apply 方法

var obj = {a: 'Custom'};

// 这个属性是在global对象定义的。
var a = 'Global'; function whatsThis(arg) {
return this.a; // this的值取决于函数的调用方式
} whatsThis(); // 'Global'
whatsThis.call(obj); // 'Custom'
whatsThis.apply(obj); // 'Custom'

在JavaScript定义的函数都继承自Function,我们可以通过Function.prototype属性里的call或apply方法将 this 值绑定到调用中的特定对象。

function add(c, d) {
return this.a + this.b + c + d;
} var o = {a: 1, b: 3}; // 第一个参数是作为‘this’使用的对象
// 后续参数作为参数传递给函数调用
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
// 第一个参数也是作为‘this’使用的对象
// 第二个参数是一个数组,数组里的元素用作函数调用中的参数
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

使用 call 和 apply 函数的时候要注意,如果传递给 this 的值不是一个对象,JavaScript 会尝试使用内部 ToObject 操作将其转换为对象。因此,如果传递的值是一个原始值比如 7 或 ‘foo’,那么就会使用相关构造函数将它转换为对象,所以原始值 7 会被转换为对象,像 new Number(7) 这样,而字符串 ‘foo’ 转化成 new String(‘foo’) 这样,例如:

function bar() {
console.log(Object.prototype.toString.call(this));
} //原始值 7 被隐式转换为对象
bar.call(7); // [object Number]

2. 箭头函数

箭头函数没有自己的this指针。通过 call() 或 apply() 方法调用一个函数时,只能传递参数(不能绑定this)。在封闭的词法环境中,箭头函数的this和普通函数的this一致;在全局代码里,箭头函数的this被设置为全局对象。

var obj = {
bar: function() {
var x = (()=> this);
return x;
}
}
// 以obj为对象来调用bar(),所以this绑定的是obj
var fn = obj.bar();
console.log(fn() === obj); // true // 这里并没有调用bar(),只是引用bar赋给fn2
var fn2 = obj.bar;
// 使用全局变量来调用bar(),所以这里的this绑定全局
console.log(fn2()() == window);

3. 对象中的函数

当函数在对象中被调用时,this指向的是调用该函数的对象。

const app = {
name: 'xiaohong',
f: function() {
console.log(this.name);
}
}

f() 函数里的this指向的是app对象。

this 的绑定只受最靠近的成员引用的影响。例如:

var o = {prop: 37};

function independent() {
return this.prop;
} o.f = independent; console.log(o.f()); // logs 37 o.b = {g: independent, prop: 42};
console.log(o.b.g()); //

事实证明,这与他是对象 o 的成员没有多大关系,最靠近的引用才是最重要的。

原型链中的this

如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,就像该方法在对象上一样。

var o = {
f: function() {
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 4; console.log(p.f()); //

在这个例子中,对象p没有属于它自己的f属性,它的f属性继承自它的原型。虽然在对 f 的查找过程中,最终是在 o 中找到 f 属性的,这并没有关系;查找过程首先从 p.f 的引用开始,所以函数中的 this 指向p。也就是说,因为f是作为p的方法调用的,所以它的this指向了p。

getter 与 setter 中的 this
用作 getter 或 setter 的函数都会把 this 绑定到设置或获取属性的对象。

bind(this)
ES5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。bind绑定的参数只生效一次

function f(){
return this.a;
} var g = f.bind({a:"azerty"});
console.log(g()); // azerty var h = g.bind({a:'yoo'}); // bind只生效一次!
console.log(h()); // azerty

传入bind的第二个参数以及后面的,依照先后顺序构成绑定函数的参数。

var foo = {
x: 3
}
var bar = function(){
console.log(this.x);
}
bar(); // undefined var boundFunc = bar.bind(foo); boundFunc(); //

有时候,我们须要保持this的上下文,也就是在一个运行环境中,想要訪问到的this值。在什么时候须要这么做呢?

比方说将一个对象的方法赋值给了一个全局变量,然后在全局变量中调用这种方法,那么this值就不再是原来的对象而是window对象了。但是我们还需要依照对象的方法来调用。

又比方说一个方法中包括了闭包,闭包是无法訪问到其外部函数的this对象的,由于this对象是在调用方法的时候自己主动生成,内部函数在搜索这两个变量的时候仅仅会搜索到其自身的活动对象。而不会沿着作用域链往外搜索,所以闭包訪问不到外部函数的this值。

在react中,常看到

export default class App extends Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
} foo() {
// todo something
} render() {
return (
<View>
<Button onPress={this.foo()}/>
</View>
)
}
}

如果你传递一个函数名给一个变量,然后通过在变量后加括号’()'来调用这个方法,此时方法内部的this的指向就会丢失。这就会出现外部的foo方法内部的this会丢失指向。

为了解决这个问题,我们需要在实例化对象的时候,需要在构造函数中绑定this,使得无论事件处理函数如何传递,它的this的指向都是固定的,固定指向我们所实例化的对象。

原文链接:https://blog.csdn.net/u013003052/article/details/87894194

this与bind(this) (es5新增)的更多相关文章

  1. 4日6日--ES5新增数组方法

    forEach使用的函数调用,所以占内存比较大,不如定长for循环和迭代for循环 1.通过forEach将数组中的元素逐个表示出来(遍历方法,读取操作). 2.通过map将原数组中的元素进行算数运算 ...

  2. String方法,js中Array方法,ES5新增Array方法,以及jQuery中Array方法

    相关阅读:https://blog.csdn.net/u013185654/article/details/78498393 相关阅读:https://www.cnblogs.com/huangyin ...

  3. js数组定义和方法 (包含ES5新增数组方法)

    数组Array 1. 数组定义 一系列数据的集合成为数组.数组的元素可以为任何类型的数据(包括数组,函数等),每个元素之间用逗号隔开,数组格式:[1,2,3]. 2. 数组创建方式 (1) 字面量方法 ...

  4. ES5新增数组方法测试和字符串常见API测试

    首先是ES5新增数组方法测试: <!DOCTYPE html><html lang="en"><head> <meta charset=& ...

  5. ES5新增的数组方法

    ES5新增:(IE9级以上支持)1.forEach():遍历数组,无返回值,不改变原数组.2.map():遍历数组,返回一个新数组,不改变原数组.3.filter():过滤掉数组中不满足条件的值,返回 ...

  6. 学习笔记-es5新增的一些数组的API(不全)-字符串-字符串API(不全)

    ### es5新增的数组的api + indexOf() 搜索数组中的元素,并返回它所在的位置. arr.indexOf(str,index) 参数: str为要查找的字符串 index为开始查找的下 ...

  7. ES5新增数组的方法

    ES5新增数组的方法 ES5新增数组常见方法(indexOf/forEach/map/filter/some/every) .indexOf( data , start)  检测数组中是否存在指定数据 ...

  8. ES5新增数组方法every()、some()、filter()、map()

    JavaScript ES5标准中新增了一些Array方法,如every().some().filter().map().它们的出现使我们能够更加便利地操作数组,但对IE9以下浏览器的兼容性比较差.下 ...

  9. ES5新增内容

    一.数组API实际开发中forEach和map会多一些=>是es6语法中的arrow function举例:(x) => x + 6相当于function(x){return x + 6; ...

随机推荐

  1. [Silverlight 4] Textbox style模擬Textblock 使可以選取、複製

    childwindow 做為訊息視窗,使用textblock,可是textbloc無法選取內容及複製, 就改用textbox假裝成textblock ---原本的textblock <contr ...

  2. Python实现抽样分布的验证(正态分布、卡方分布、T分布)

    参考链接:https://github.com/v-gazh/LearningStatsGroup/blob/master/week7/week7.ipynb 源地址:https://github.c ...

  3. String类常用功能

    String类常用功能 判断: boolean equals(Object obj) boolean equalsIgnoreCase(String str) //忽略大小写 boolean star ...

  4. Android 一个TextView中设置多种不同大小的字体,设置超链接

    以前项目中要是遇到这样的UI设计,都是傻不拉唧的分为三个TextView来实现,今天在微信中无意中看了一篇公众号文章,发现原来只要一个TextView就可以搞定啦,人生最悲哀的事情莫过于工作了这么久啦 ...

  5. Kotlin开发springboot项目(一)

    Kotlin开发springboot项目(一) Kotlin语言与Xtend语言有很多相似之处 为什么会存在这么多JVM语言? 现存的语言提供了太过受限制的功能,要不就是功能太过繁杂,导致语言的臃肿和 ...

  6. Vim文本编辑器详细用法

    1 Vi.Vim文本编辑器 1.Vi.Vim Vi是Visual interface的简称. Vim是Vi的增强版,即Vi Improved.在后面的实例中将介绍Vim的使用. 为什么学vi? 1)所 ...

  7. python常用库(转)

    转自http://www.west999.com/info/html/wangluobiancheng/qita/20180729/4410114.html Python常用的库简单介绍一下 fuzz ...

  8. iview admin动态路由实现

    参考 https://blog.csdn.net/weixin_41538490/article/details/93749942

  9. Python 文件读写操作实例详解

    Python提供了必要的函数和方法进行默认情况下的文件基本操作.你可以用file对象做大部分的文件操作 一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法.1.得到当前 ...

  10. BEST FREE UNITY ASSETS – OVER 200 CURATED QUALITY ASSETS

    http://www.procedural-worlds.com/blog/best-free-unity-assets-categorised-mega-list/ BEST FREE UNITY ...