方法、this的讲解、apply&call&bind的理解

方法与函数

在一个对象中绑定函数,称为这个对象的方法。



this的各种坑!!!

1. 先来个正常的,this指向执行环境的对象

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};
xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了

2. “this指向执行环境的对象

 function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}
var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};
xiaoming.age(); // 25, 正常结果
getAge(); // NaN

function getAge是绑定在window下的函数,就相当于window的方法,this指向window理所当然。


getAge此时是回调函数。等同于如下写法:(与1中一样)

var xiaoming = {
    name: '小明',
    birth: 1990,
    age:  function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
    
};

与此类似:

var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN

非严格模式下,变量未被定义就被调用,返回NaN。(没毛病)


'use strict';

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};

var fn = xiaoming.age;
fn(); // Uncaught TypeError: Cannot read property 'birth' of undefined

严格模式下,变量未被定义就被调用,返回undefined(指向Undefined对象)。(没毛病)


总之:正确的姿势是object.xxx()的调用指向正确

xiaoming.age()//this指向xiaoming

3. 修复方法。用一个that变量首先捕获this

 'use strict';

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法内部一开始就捕获this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth; // 用that而不是this
        }
        //定义其他方法,而不是把所有语句都堆到一个方法中
        function getAgeFromBirth(){
            var return that.birth;
        }
        return getAgeFromBirth();
    }
};

var that = this;,你就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。

xiaoming.age(); // 25

4. 用arguments.callee()代替this也是不可以的。

arguments.callee()指向当前调用的函数,常用在匿名函数里指代该匿名函数。



apply()call()bind()理解

1. 要指定函数的this指向哪个对象,可以用函数本身apply()方法

apply vt. “应用”的意思。apply the Function to Object.(将函数应用于某对象)
call vt.vi."需要"的意思。call for the Object.(需要某对象来运行这个函数)

简单粗暴的这样理解,便于记忆。

apply(thisObj,args)
thisObj表示函数内this所指代的对象(Obj)(是谁),备选值:this null object实例

  • thisObjthis时,调用apply()的函数中this所指代的对象
  • thisObjnull时,thisObj使用全局对象
  • thisObjobject实例时,很常见

args表示传入的参数,可以是argumentArray实例
返回function执行的值

例如:

//将默认的Object.toString()应用到对象o上,以覆盖对象o中自定义的toString()方法。
Object.prototype.toString().apply(o);
//调用Math.max()方法来查找数组中的最大元素
var data = [1,2,3,4,5,6];
Max.max.apply(null,data);
window.color = "red";
var o = {
    color:"blue";
    }
function sayColor(){
    alert(this.color);
    }
sayColor(); //red
sayColor().apply(this);//red
sayColor().apply(window);//red
sayColor().apply(o);;//blue

call()apply()类似
call(thisObj,arg1,arg2,......)

  • arg1,arg2,......表示按照顺序传入参数。

2. bind() ES5新增

bind vi. “捆绑”的意思。bind the Function to the Object.(将函数绑入对象里面,函数此时成了该对象的方法,也就是说,此时函数内的this指向绑定的对象o

bind(o,arg1,arg2,....)

例如:

function getName() {
    console.log(this.name);
    }
var o = {
    name:xiaoxiao;
    age:18;
    };
var result=getName().bind(o);
result();//xiaoxiao
getName();//undefined or NaN

参数可以分两次传递:

//假设f为一个函数
var g = f.bind(0,1,2);
//此时g为一个新函数,g(3)等价于:
f.call(0,1,2,3);

var o1={
    x:1,
    getplus:function(y,z){
      return this.x+y+z;
    }
  }
  var o2={
    x:11,
    getplus:function(y,z){
      return this.x*y;
    }
  }
  //o1.getplus需要2个参数,分两次传入
  var result=o1.getplus.bind(o2,1);
  //得到的result是函数,函数result需要另一个参数才能计算x+y+z的值
  result(3);//得出计算结果
  var resultapply=o1.getplus.call(o2,1,2);//与上面两步得出的结果一样

使ES3也兼容bind()的方法:

//如果方法不存在,就在原型里添加
//提示:bind()返回的是函数
if(!Function.prototype.bind){
    Function.prototype.bind=function(o /*,args*/){
        var self=this,boundArgs=arguments;
            //**此时Function是对象,this指向Funtion本身**,并把它保存起来
            //arguments也保存起来,这里的arguments是第一次传入的参数,所以下面for循环从第二个参数开始
        return function(){
            var args=[],i;
            for(i=1;i<boundArgs.length;i++) args.push(boundArgs[i]);
                //遍历第一次传入的参数,从第二位开始(第一位是对象)
            for(i=0;i<arguments.length;i++) args.push(arguments[i]);
                //遍历第二次传入的参数,全部遍历
            return self.apply(o,args);
        }
    }
}
self为何指代被调用的方法

解释:self的值是指向function的指针。

var result=o1.getplus.bind(o2,1);

其中o1.getplus方法(函数)是图中红色的Function对象,而self指针是图中的小this

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容