this在全局作用域下
浏览器中指向为:window
node环境中指向:空对象
通常都是在函数中使用,所有的函数在被调用时,都会创建一个执行上下文:
这个上下文中记录着函数的调用栈、AO对象等;this也是其中的一条记录
-
函数在调用时,JavaScript会默认给this绑定一个值;
-
this的绑定和定义的位置(编写的位置)没有关系;
-
this的绑定和调用方式以及调用的位置有关系;
-
this是在运行时被绑定
function foo() {
console.log(this)
}
//1.直接调用
foo() //window
//2.对象调用
var obj = {
name: 'why',
foo: foo
}
obj.foo() //foo函数
//apply
foo.apply('abc') //[String:'abc']
规则一:默认绑定
调用的位置
独立的函数调用 我们可以理解成函数没有被绑定到某个对象上进行调用;
function foo() {
console.log(this)
}
foo()
function foo1() {
console.log(this)
}
function foo2() {
console.log(this)
foo1()
}
function foo3() {
console.log(this)
foo2()
}
foo3()
var obj = {
name: 'why',
foo: function () {
console.log(this)
}
}
var bar = obj.foo()
//this指向依旧为全局
bar()
绑定二:隐式绑定;
通过某个对象发起的函数调用
隐式绑定有一个前提条件:
必须在调用的对象内部有一个对函数的引用(比如一个属性); 如果没有这样的引用,在进行调用时,会报找不到该函数的错误; 正是通过这个引用,间接的将this绑定到了这个对象上;
var obj = {
name: 'why',
foo: foo
}
obj.foo()
绑定三:显示绑定(apply,call,bind)
如果我们不希望在 对象内部 包含这个函数的引用,同时又希望在这个对象上进行强制调用,该怎么做呢? JavaScript所有的函数都可以使用call和apply方法(这个和Prototype有关)。
其实非常简单,第一个参数是相同的,后面的参数,apply为数组,call为参数列表;
这两个函数的第一个参数都要求是一个对象,这个对象的作用是什么呢?就是给this准备的。
在调用这个函数时,会将this绑定到这个传入的对象上。 因为上面的过程,我们明确的绑定了this指向的对象,所以称之为 显示绑定。
如果在显示绑定中,我们传入一个null或者undefined,那么这个显示绑定会被忽略,使用默认规则:
function foo() {
console.log(this)
}
var obj = {
name: 'obj'
}
//指定this绑定
foo.call(obj)
foo.call(null)
foo.call(undefined)
foo.apply({ name: 'apply' }) //{name:'apply'}
foo.call({ name: 'call' }) //{name:'call}
foo.bind({ name: 'bind' }) //{name:'bind'}
//call 和 apply 区别
function sum(sum1, sum2) {
console.log(sum1 + sum2, this)
}
// 传参数不同 挨个传
sum.call('call', 20, 30)
// 数组传参
sum.apply('apply', [20, 30])
绑定四:new绑定
this = 创建出来的对象
JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字。
使用new关键字来调用函数是会执行如下的操作:
1.创建一个全新的对象;
2.这个新对象会被执行prototype连接;
3.这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成);
4.如果函数没有返回其他对象,表达式会返回这个新对象;
function Person(name, age) {
this.name = name
this.age = age
console.log(this)
}
var p1 = new Person('why', 18)
console.log(p1)
规则优先级
-
1.默认规则的优先级最低
毫无疑问,默认规则的优先级是最低的,因为存在其他规则时,就会通过其他规则的方式来绑定this
-
2.显示绑定 优先级高于 隐式绑定
-
3.new绑定 优先级高于隐式绑定
-
4.new绑定 优先级高于
bindnew绑定和call、apply是不允许同时使用的,所以不存在谁的优先级更高
new绑定可以和bind一起使用,new绑定优先级更高
间接函数引用
创建一个函数的 间接引用,这种情况使用默认绑定规则。
赋值(obj2.foo = obj1.foo)的结果是foo函数;
foo函数被直接调用,那么是默认绑定
function foo() {
console.log(this)
}
var obj = {
name: 'why',
foo: foo
}
var obj2 = {
name: 'obj2'
}
//函数间接调用
;(obj2.foo = obj.foo)()//window
箭头函数 arrow function [ ()=> ]
箭头函数不会绑定this、arguments属性;
箭头函数不能作为构造函数来使用(不能和new一起来使用,会抛出错误);
箭头函数不使用this的四种标准规则(也就是不绑定this),而是根据外层作用域来决定this。
var num = [1, 5, 6, 7]
//1.一个参数,省略小括号
num.forEach(item => {
console.log(item)
})
//2.只有一行执行体,{}也可以省略,默认将这行代码的执行结果为返回值
num.forEach(item => console.log(item))
var reult = num
.filter(item => item > 2)
.map(item => item * 2)
.reduce((preValue, item) => preValue + item)
console.log(reult)