搞懂this指向
ps 为什么要搞懂this?因为JavaScript是面向对象编程,而this指向的就是对象
谁调用就指向谁
例子:
function test() {
var name = "测试";
console.log(this.name); // ''
console.log(this); // window
}
test();
this最终指向的是调用它的对象,这里的函数test实际是被Window对象所点出来的。
function test() {
var name = "测试";
console.log(this.name); // ''
console.log(this); // window
}
window.test();
效果是一样的,因为定义的函数也是window的一个属性。
在看另外个例子
var test = {
name: '测试',
fn: function() {
console.log(this.name); // 测试
}
}
test.fn()
这里this是指向对象test,按说法谁调用它就指向谁,那自然就是对象test。当然要在函数创建后这个说法才成立。
this永远指向的是最后调用它
var test = {
age:10,
test2:{
age:12,
fn:function(){
console.log(this.age); //undefined
console.log(this); //window
}
}
}
var call = test.test2.fn;
call();
这里指向的是window,因为this永远指向的是最后调用它的,也就是看它执行的时候是谁调用的。这个例子虽然函数fu是被test2所引用,但是在将fn赋值给变量call的时候并没有执行所以最终指向的是window
构造函数版this
function fn(){
this.user = "测试";
}
var test = new fn();
console.log(test.user); // 测试
这里之所以对象test可以点出函数Fn里面的user是因为new关键字可以改变this的指向,用了new关键字就是创建一个对象实例,我们这里用变量test创建了一个fn的实例(相当于复制了一份Fn到对象test里面),此时仅仅只是创建,并没有执行,而调用这个函数fn的是对象test,那么this指向的自然是对象test。
首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。
当this碰到return时
function fn()
{
this.user = '测试';
return {};
}
var test = new fn;
console.log(test.user); //undefined
function fn()
{
this.user = '测试';
return 1;
}
var test = new fn;
console.log(test.user); //测试
如果函数返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
自行改变this的指向
开发环境的数据,测试环境没有开发环境的数据,只有改变环境才能更换数据。call,apply,bind 就是一般用来指定this的环境
call()
var test = {
age:10,
test2:{
age:12,
fn:function(){
console.log(this.age); //undefined
console.log(this); //window
}
}
}
var fn2 = test.test2.fn;
fn2();
这里fn2指向的是window,通过call方法,第一个参数可以将fn2 window环境指向为你需要的环境中
var test = {
age:10,
test2:{
age:12,
fn:function(){
console.log(this.age); // 12
}
}
}
var fn2 = test.test2.fn;
fn2.call(test);
也可以添加多个参数
var test = {
age:10,
test2:{
age:12,
fn:function(e, ee){
console.log(this.age); // 12
console.log(e+ee); //3
}
}
}
var fn2 = test.test2.fn;
fn2.call(test, 1, 2);
apply()
apply方法和call方法有些相似,它也可以改变this的指向,唯一不同的就是apply第二个参数只能是数组
var test = {
age:10,
test2:{
age:12,
fn:function(e, ee){
console.log(this.age); // 12
console.log(e+ee); //6
}
}
}
var fn2 = test.test2.fn;
fn2.call(test,[1,2,3]);
ps 注意如果call和apply的第一个参数写的是null,那么this指向的是window对象
bind()
bind方法和call、apply方法有些不同,bind方法是返回的是一个修改过后的函数。
var test = {
age:10,
test2:{
age:12,
fn:function(){
console.log(this.age);
}
}
}
var fn2 = test.test2.fn;
fn2.bind(test);
这样会发现是没有执行的,因为bind返回的是一个修改后的函数,没有调用他
var test = {
age:10,
test2:{
age:12,
fn:function(){
console.log(this.age); // 12
}
}
}
var fn2 = test.test2.fn;
var fn3 = fn2.bind(test);
fn3()
这样就可以调用,当然bind也是支持多个参数的,用法跟call一样