this指向
默认绑定
函数在调用的时候没有任何前缀,会有默认绑定,默认绑定window对象
function fn1() {
let fn2 = function () {
console.log("fn2",this); //window
fn3();
};
console.log("fn1",this); //window
fn2();
}
function fn3() {
console.log("fn3",this); //window
}
fn1();
// fn1-fn2-fn3
console.log(this === window); // true
this.a = 100;
console.log(window.a); // 100
console.log(a); //100
var b = 200;
console.log(window.b); //200
let c = 300;
console.log(window.c); // undefined ,let不是全局的
隐式绑定
如果函数在调用的时候,前面存在一个调用对象,那么this就会绑定在他身上 谁调用指向谁
此处的this指向obj
function fun1() {
console.log(this); // obj
}
let obj = {
name: "青龙白虎",
func: fun1,
};
obj.func();
let name = "zs";
let obj = {
name: "pyy",
age: 17,
say: function () {
return `我叫${this.name}我今年${this.age}岁`;
},
};
let say = obj.say;
// 注意:
// this关键字是在函数调用时才做绑定的,
// say()前面是什么?什么都没有,因此this关键词就将指向全局window。
// console.log(say()); //我叫我今年undefined岁
// 正确
// console.log(obj.say()) //我叫pyy我今年17岁
如果是前面有多个对象,this指向最近的对象
function fun1() {
console.log(this.name); // 青龙白虎
}
let obj = {
name: "青龙白虎",
func: fun1,
};
let obj2 = {
name: "朱雀玄武",
o:obj
};
obj2.o.func();
显示绑定,区别
在代码中使用call,apply,bind来实现绑定
bind是返回一个函数,所以要再次调用
let obj = {
name: "成都校区",
};
let obj2 = {
name: "马特里卡",
};
let obj3 = {
name: "阿多比",
};
function func() {
console.log(this.name);
}
func(); // 空
func.call(obj); // 成都校区
func.apply(obj2); // 马特里卡
// 注意bind不会立即执行,会返回一个函数,因此要再次调用
func.bind(obj3)(); // 阿多比
区别:
1.call、apply
f.call(新的this指向,参数1,参数2,参数3,...)
f.apply(新的this指向,[参数1,参数2,参数3,...])
// 两者的唯一区别就是参数,call是直接书写,以逗号间隔,apply是一个数组包裹
注意:apply,call会立即执行一次。
2.bind
f.bind(新的this指向,参数1,参数2,参数3,...)
f.bind()
会创建一个与f
具有相同函数体和作用域的函数,因此改变了指向后要再次调用一次,无论这个函数是如何被调用的。也就是说,bind只生效一次。
new 创建对象
this指向stu,谁创建实例this指向谁
function Student() {
this.name = "小明";
console.log(this.name); // 小明
}
let stu1 = new Student();
// age是挂在原型身上的,好处是就算new 100个Student原型上都只有一个age
// 不会占用栈的空间,优化了内存
stu1.__proto__.age = "18"; // 挂在原型上
console.log(stu1);
this绑定的优先级
显示绑定>隐士绑定>默认绑定
new绑定>隐士绑定>默认绑定
箭头函数的this
es6的箭头函数是另类存在,箭头函数的this不适合前面的任何规则
箭头函数的this取决于外层作用域的this,外层函数this指向谁,箭头函数内部的this就指向谁
function func() {
//obj1
return () => {
console.log(this.name);
};
}
let obj1 = {
name: "成都",
};
let obj2 = {
name: "武汉",
};
// 箭头函数this 外层的作用范围
// func()(); // window
let bar = func.call(obj1);
bar() //成都
bar.call(obj2); //chengdu,指向最近的this
bar.bind(obj2)(); //chengdu bind会再次调用
综合练习this
var name = "window";
let obj = {
name: "obj",
o: {
name: "o",
f: function () {
return this.name;
},
},
f: function () {
return this.name;
},
};
console.log(obj.o.f()); // o
console.log(obj.f()); // obj
let name1 = obj.f;
let name2 = obj.o;
console.log(name1()); // window名字
// window名字,因为this指向window,
// window对象有name属性叫window
console.log(name2.f()); // o
// 在js中我们都是从左读到右。于是this指向o而不是obj,这是一个很重要的区别
// f()是被obj对象调用的,在这种情况,obj里的f函数返回this.name。this指向obj了,那obj就是返回值。
// this关键词是在函数调用时才做绑定的,name1()前面是什么?什么都没有,因此this关键词就将指向全局window。
// 因为f是name2调起的,而name2指向o,所以输出o
*箭头函数需要注意哪些地方?*
当要求动态上下文的时候,就不能够使用箭头函数,也就是this的固定化。
\1. 在使用=>定义函数的时候,this的指向是定义时所在的对象,而不是使用时所在的对象;
\2. 不能够用作构造函数,这就是说,不能够使用new命令,否则就会抛出一个错误。
\3. 不能够使用arguments对象;
\4. 不能使用yield命令