好!欢迎访问迷津渡口 现在时间是:

迷津渡口

越感到迷惑 越接近真理

javascript中this详解

javascript面向对象中this是非常重要的一个关键字。


理解this的原则:

1. 当一个函数或方法被调用时,拥有它的object会作为this传入。
2. new调用构造函数时this为实例化对象。
3. 可使用函数或方法改变函数或方法调用的对象,从而改变this指向。


应用原则的几种情况:

普通函数调用:

普通函数调用其实是通过Global对象调用的,在浏览器中Global对象作为Window对象的一部分实现了。

因此普通函数调用时this代表的是Global或Window对象。

例一:

function testthis(x) {
    this.x=x; 
}
// this是global对象,全局变量x未定义,则在赋值时同时定义一个全局变量x
testthis(7);
console.log(x);

结果为:

7

例二:

function testthis(x) {
    this.x=x;
}
// 定义声明一个全局变量x
var x=100;
console.log(x);
// this是global对象,全局变量x已定义,则修改全局变量x的值
testthis(7);
console.log(x);

结果为:

100
7

构造函数调用:

构造函数调用时会生成一个新对象,此时this代表的就是构造出来的新对象。

例子:

function Test(x) {
    this.x=x;
}
// 构造实例化对象时,this就是实例化的对象,因此x成为新对象的属性
var test=new Test(7);
console.log(test.x);

结果为:

7

对象方法调用:

一个对象调用方法时,this指的就是调用方法的对象。

例子:

function Test(x) {
    this.x=x;
    this.getX=function () {
        console.log(this.x);
    };
}
var test=new Test(7);
// 此时调用getX方法的是test对象,因此里面的this指的是test对象
test.getX();

结果为:

7

setTimeout和setInterval里this的转变

由于setTimeout和setInterval是普通函数调用,因此函数作用域里this指的是global对象。

在构造函数里,如果需要在setTimeout和setInterval函数里面获取实例化对象,需要借用变量获取,常用that变量名。

例子:

function Test(x) {
    this.x=x;
    this.getX=function() {
        console.log(x);
    };
    this.delayGetX=function() {
        // 错误:此时this为调用setTimeout的对象,即global对象,实际应为Test的实例化对象
        // setTimeout(this.getX,1000);  
        // 正确方法:
        // 首先将调用delayGetX的this对象,即Test实例化对象,赋值给that
        // 然后在setTimeout里面采用that调用getX方法
        var that=this;
        setTimeout(that.getX,1000); 
    };
}

结果为:

7

call和apply方法修改函数或方法调用对象

javascript提供了call和apply方法用于修改函数或者方法的调用对象。

例一:修改普通函数的调用对象

function test() {
    console.log(this.x);
}
// 定义一个全局变量x
var x=100;
// 直接调用this指的是全局对象global
test();

function TestX(x) {
    this.x=x;
}
// 实例化一个TestX对象
var testx=new TestX(7);
// 调用test函数,但此时this指向的对象是testx
test.call(testx);

结果为:

100
7

例二:修改方法调用的调用对象

function Test1(x,y) {
    this.x=x;
    this.y=y;
    this.add=function() {
        console.log(this.x+this.y);
    };
}
function Test2(x,y) {
    this.x=x;
    this.y=y;
}
// 实例化Test1对象,具有add方法
var test1=new Test1(1,2);
// 实例化Test2对象,并没有add方法
var test2=new Test2(3,4);
// 对象方法调用,此时方法的this指向test1对象
test1.add();
// 使用call方法修改add方法的this指向的对象,此时为test2对象
test1.add.call(test2);

结果为:

3
7

例三:使用call函数实现类继承

function Person(name) {
    this.name=name;
    this.showName=function() {
        console.log(this.name);
    };
}
function Student(name,school) {
    // 在Student构造函数里面调用Person构造函数
    // 将Student构造函数的实例化对象传递给Person构造函数
    // 此时调用Person构造函数的对象为Student实例化对象
    // 从而实例化Student对象可以继承Person的属性name和方法showName
    Person.call(this,name);
    this.school=school;
    this.showSchool=function() {
        console.log(this.school);
    }
}
// 光棍节来个宇宙泡妞学院^_^
var student=new Student('小指','宇宙泡妞学院');
// 调用继承来的showName方法
student.showName();
// 调用自己新定义的showSchool方法
student.showSchool();

结果为:

小指
宇宙泡妞学院

例四:使用apply函数使用Array对象的方法

apply函数和call函数的区别是:

apply函数的参数有两个,一个是thisObj,即传递调用修改的this对象,一个是参数数组。

call函数的参数包含多个,一个是thisObj,同上,另外是不定长的普通的参数。

两者thisObj参数是必选参数,剩下的是可选参数。

apply函数常用的场景是使数组里面的每个参数都可以使用数组对象方法:

var a=new Array(1,2,3);
var b=new Array(4,5,6);
// 合并a数组和b数组到a数组
a.push.apply(a,b);
console.log(a);

结果:

[1, 2, 3, 4, 5, 6]


小指才疏学浅,本文若有不足之处,请不吝赐教~

点赞0
   支持一下
挤眼 亲亲 咆哮 开心 想想 可怜 糗大了 委屈 哈哈 小声点 右哼哼 左哼哼 疑问 坏笑 赚钱啦 悲伤 耍酷 勾引 厉害 握手 耶 嘻嘻 害羞 鼓掌 馋嘴 抓狂 抱抱 围观 威武 给力
 点赞
 签到
 表情
 图片
 代码
提交评论

清空信息
关闭评论
 00:00/00:00
我想和你虚度时光 - 花房姑娘(9)
  1. 恋恋风尘
  2. 恋恋风尘
  3. 恋恋风尘
  4. 恋恋风尘
  5. 恋恋风尘
  6. 恋恋风尘
  7. 恋恋风尘
  8. 恋恋风尘
  9. 恋恋风尘