一 、关于this
Javascript中的this经常让人糊涂,但总的一个原则就是,this总是指向一个对象,而具体指向哪个对象是在javascript执行阶段由执行环境动态绑定的,而非在javascript初始化阶段声明时的环境
实际中,this的指向大概分为以下四类:
(1) 作为对象的方法调用
(2) 作为普通函数调用
(3) 构造器调用
(4) Function,prototype.call或Function.prototype.apply,动态的改变出入函数的this
1.作为对象的方法调用时,this指向改对象
var obj = {
name:"xiaoming",
age:25,
say:function(){
alert(this === obj);
alert("我叫" + this.name + "我今年" + this.age + "岁");
}
};
obj.say();
2.作为普通函数调用,this总是指向全局对象window
alert(this); //window
var name = "xiaoming";
function getName(){
return this.name;
}
alert(getName()); //xiaoming
3. 构造器调用, 当用 new 运算符调用函数时,该函数总是会返回一个对象,通常情况下,构造函数里的 this 就指向返回的这个对象
function Person(){
this.name = "xiaoming";
}
var xiaoming = new Person();
alert(xiaoming.name);
在构造函数中还有一种特例,那就是在构造函数中显示的返回一个对象,那这个this就不跟我们期待的一样了,例如:
function Person(){
this.name = "xiaoming";
return {
name:"我是另外一个xiaoming"
}
}
var which = new Person();
alert(which.name); //我是另外一个xiaoming
二 、接下来说说apply.call,bind的区别以及他们中的this
var xiaoming = {
name:"xiaoming",
age:25,
say:function(){
console.log("我叫"+this.name+",我今年"+this.age+"岁了。");
}
}
var xiaoli = {
name:"xiaoli",
age:27
}
xiaoming.say() //很明显,就是"我叫xiaoming,我今年25岁了"
//如果我现在想打印出xiaoli的名字,怎么办呢?那就用到了call,apply.bind
//他们的作用就是改变this指向的对象
xiaoming.say.call(xiaoli);
xiaoming.say.apply(xiaoli);
xiaoming.say.bind(xiaoli)();
从以上代码中我们发现call.bind,apply都可以改变this的指向,但是好像call和apply没什么区别呀?难道两个的作用是一样的?答案是当然不一样。
bind的区别已经很明显了,bind后面需要加一个(),这又是为什么呢?
这是因为call和apply直接返回的是函数调用后的结构,而bind方法返回的是一个函数,不信,你可以typeof一下,看返回的是不是function哦。
好,接下来解决call和apply到底有什么区别呢?如果现在我把代码改一下
var xiaoming = {
name:"xiaoming",
age:25,
say:function(school,hobby){
console.log(this.name+"|"+this.age+"|"+school+hobby);
}
}
var xiaoli = {
name:"xiaoli",
age:27
}
xiaoming.say.call(xiaoli,"shcool1","羽毛球");
xiaoming.say.apply(xiaoli,["school1","羽毛球"])
从上面可以看出,他们的区别无非就是传参的形式不一样,apply必须把参数放进数组
三、最后再来说说bind方法
bind方法就是把函数绑定到一个对象上。但里面有一点坑是,用bind返回的函数,它是没有prototype属性的。
四 .另外apply和call还能继承
function Person(name,age){
this.name = name;
this.age = age;
}
function student(name,age,className){
Person.call(this,name,age);
this.className = className;
}
var Amy = new student("Amy",25,"一年级");
console.log(Amy.age)