天天看点

javascript中this,apply,call,bind的学习笔记

一 、关于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

   首先我创建两个对象xiaoming和xiaoli,如下代码中,xiaoming有一个say方法,但是xiaoli中没有say方法,如果我想打印出xiaoli的名字,怎么办呢?

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)
           

原文链接:http://www.w3cfuns.com/notes/20528/031d0633393438dc8cb6ea7ef8796d45.html

继续阅读