(1) 全局作用下 this指向window
console.log(this);
(2) 函数独立调用下 this指向window
function test(){
console.log(this);
}
test()
函数执行,this才会指向,才有意义,每一个函数执行都会有一个自身的this指向。 函数不执行,this没意义。每个this都代表着函数的执行。
var a = 0;
var obj = {
a: 2,
foo: function(){
console.log(this); //obj
function test(){
console.log(this); //window
}
test();
}
}
obj.foo()
答案
obj.foo()方法执行 到 log(this) 此时的this指向调用这个方法的对象obj
test() 函数执行, 此时是函数的独立调用,因此this指向window
// 立即执行函数
// 第一种写法(function(){})()
(function(){
console.log(this);
})();
// 第二种写法(function(){}())
(function(){
console.log(this);
}())
var a = 0;
var obj = {
a: 2,
foo: function(){
function test(){
console.log(this);
}
return test;
}
}
obj.foo()()
答案:this指向window
分析: obj.foo()执行完毕返回test,然后变成了test()这仍是以一个函数的独立调用,所以this指向window
var a = 0;
function foo(){
console.log(this);
}
var obj = {
a: 2,
foo: foo
}
obj.foo() // 指向obj
var bar = obj.foo; //指向window
bar()
答案分析:
改代码等价于
var obj = {
a: 2,
foo: function(){
console.log(this)
}
}
obj.foo() 这属于对象的方法调用,所以this指向调用该方法的对象obj
2)
//var bar = obj.foo 等价于
var bar = function(){
console.log(this)
}
bar() //这属于函数的独立调用,所以this指向window
(5) 参数赋值
var a=0;
function foo(){
console.log(this);
}
function bar(fn){
console.log(this); //这个是函数bar的this 指向window
fn();
}
var obj = {
a:2,
foo:foo
}
bar(obj.foo)
答案分析
此时obj.foo是一个形参, 代表foo函数 所以fn()就等于foo() 属于独立调用,this指向window
call(this指向的对象,参数1,参数2…)
apply(this指向的对象,[参数1,参数2…])
bind(this指向的对象)(参数1,参数2…)
undefine、 null无包装类,如果将其作为this指向对象则绑定失败,采用默认的绑定方式window
function Person(){
//构造函数 和new一起使用才起效果
}
new Person()
new的执行步骤
创建一个新的内存空间,放入一个空的对象
将this指向这个对象
执行构造函数的代码,为对象创建属性和方法
返回创建的对象
this绑定的优先级
new绑定>显式绑定>隐式绑定>默认绑定
(1) 默认绑定规则优先级最低
(2)隐式和显示的比较
// 优先级的比较
function foo(){
console.log(this);
}
var obj1 = {
a:2,
foo:foo
}
var obj2 = {
a:3,
foo:foo
}
// 1. 隐式绑定
// obj1.foo()
// 2. 显示绑定
obj1.foo.call(obj2)
obj2.foo.call(obj1)
结果
{a: 3, foo: ƒ}
{a: 2, foo: ƒ}
结果显示
obj1.foo.call(obj2) 前半部分属于隐式绑定,后又用了显式绑定,this指定了显式绑定的对象,因此,显式绑定的优先级>隐式绑定
(3)显式绑定和new 绑定的比较
function foo(b){
this.a = b
}
var obj1 = {};
var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a);
var baz = new bar(3);
console.log(obj1.a);
console.log(baz.a);
答案分析
var bar = foo.bind(obj1) 属于函数的赋值,并且this强制指向了obj1
bar(2) 执行bar ,将2传入foo函数,执行obj1.a = 2
log(obj1.a) 输出2
var baz = new bar(3) new中this指向的是新创建的对象baz,bar强制指向了obj1,因为new的优先级>显式绑定,所以this指向了baz,执行baz.a = 3;
所以在输出obj1.a为2. baz.a =3
(参数1, 参数2)=>{
函数体)
=>代表了function关键字
(1)
箭头函数的内部并没有this指向,箭头函数的this指向是由外层函数的作用域决定的。
var a = 0;
function foo(){
// var that = this;
console.log(this);
var test = () => {
console.log(this);
}
test();
}
var obj1 = {
a:2,
foo:foo
}
obj1.foo();
输出结果: this指向了obj1
{a: 2, foo: ƒ}
{a: 2, foo: ƒ}
(2)
var a = 0;
function foo() {
console.log(this);
var test = () => {
console.log(this);
}
return test;
}
var obj1 = {
a: 1,
foo: foo
}
var obj2 = {
a: 2,
foo: foo
}
obj1.foo()();
分析:
此时的obj1.foo()执行第一个log(this)this指向obj1,并返回test ,即得到test()独立调用函数,但是默认绑定规则对箭头函数无效,因此test函数体内的this并不指向window,箭头函数没有this,它只能那他的父级作用域所指向的this,因此依旧指向obj1
(3)
var obj1 = {
a: 1,
foo: ()=>{
console.log(this);
}
}
obj1.foo()
答案分析:
如果foo不是箭头函数,那么this指向obj1, 但是因为箭头函数内部没有this指向,因此取其父级找,这里的父级是全局,所以this指定window
总结:
所有的this绑定对箭头函数不适用
箭头函数内部的this指向取决于其父级的this(保持一致)
练习
// 综合大练习
var name = 'window'
var obj1 = {
name:'1',
fn1: function(){
console.log(this.name);
},
fn2: () => console.log(this.name),
fn3: function(){
return function(){
console.log(this.name);
}
},
fn4: function(){
return () => console.log(this.name);
}
}
var obj2= {
name:'2'
}
obj1.fn1()
obj1.fn1.call(obj2);
obj1.fn2()
obj1.fn2.call(obj2)
obj1.fn3()()
obj1.fn3().call(obj2)
obj1.fn3.call(obj2)
obj1.fn4()()
obj1.fn4().call(obj2)
obj1.fn4.call(obj2)()
答案解析:
obj1.fn1() 隐式绑定,this指向obj1 所以this.name = obj1.name = ‘1’
obj1.fn1.call(obj2) 显示绑定, this强制指向obj2, 所以this.name = obj2.name = ‘2’
obj1.fn2() 和 obj1.fn2.call(obj2)
fn2 方法是箭头函数,没有自己的this指向,各种绑定均失效,其this取决于其父级,这里父级是全局作用域,因此this.name = window.name = window
obj1.fn3()() 其中obj1.fn3()是调用函数,返回值为一个函数f,
function(){
console.log(this.name);
}
f()为再调用这个函数,为单独函数调用,this指向window返回window
obj1.fn3().call2 可以这样理解
var foo = obj.fn3 = function (){ log(this.name)} 函数的声明
obj1.fn3.call(oj2)它改变的是fn3这个父级的this指向,但返回的仍是一个函数f ,f()调用仍为函数的单独调用 返回window
fn4: function(){
return () => console.log(this.name);
}
var foo = obj1.fn4();
即 foo = () => console.log(this.name) 函数的定义
obj1.fn4()() == foo() 箭头函数 其父级fn4,fn4是通过隐式绑定this指向obj1 ,所以返回obj1.name = ‘1’
obj1.fn4().call(obj2) == foo.call(obj2) 仍未箭头函数,各种绑定失效,返回其父级的指向 obj1 返回‘1’
obj1.fn4.call(obj2)() == foo.call() 但是强制将foo的父级fn4的指向到了obj2 返回obj2.name = ‘2’