03-this对象

this对象

this总是返回一个对象,也就是返回属性或者方法当前所在的对象。
可以近似地认为,this是所有函数在运行时的一个隐藏参数,指向该函数在运行时的环境对象。
如果一个函数在调用时,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
如果函数独立调用,那么该函数内部的this,则指向undefined。
在非严格模式中,当this指向undefined时,它会被自动指向全局对象window。
即函数在调用时,this总指向它的拥有者(调用者),若自己独立调用,就指向undefined,非严格模式中独立调用指向window。

    // 使用严格模式
    function foo() {
        'use strict';
        console.log(this);
    }
    foo();  // foo()独立调用 this指向undefined
    window.foo(); // foo()被window调用,this指向window

this指向在运行时确定,一旦确定,不可更改。

    var name = 'Tom';
    var obj = {
        name: 'Leo'
    };
    function sayName() {
        this = obj; // 试图在函数运行时修改this
        console.log(this.name);
    }
    sayName();//报错,函数在运调用时已确定this指向,无法更改

赋值操作会改变this指向。

    var name = 'Tom'
    function sayName() {
        console.log(this.name);
    }
    var obj = {
        name: 'Leo',
        say: sayName  // 将sayName函数的引用赋值给say
    }
    obj.say(); //Leo
    var foo = obj.say;  // 将sayName函数的的引用赋值给全局变量foo
    foo();
    // obj.say()在obj中被调用,this指向obj
    // foo()独立调用,非严格模式中,this指向window
    // 也可以理解为foo()在window中被调用,因为在全局环境中foo()==window.foo()

    var name = 'Tom';
    var obj = {
        name: 'Leo',
        foo: {
            name: 'Bob',
            sayName: function () {
                console.log(this.name);
            }
        }
    }
    obj.foo.sayName(); // Bob
    var say = obj.foo.sayName; //将sayName函数的引用地址赋值给say
    say(); // Tom 函数sayName独立执行,this指向window
    var box = obj.foo; // 将对象foo的引用地址赋值给box
    box.sayName(); // Bob  函数sayName在foo对象中执行,this指向foo

this指向函数运行时的环境对象,与函数定义时的位置无关。

    var name = 'Tom';
    var obj = {
        name: 'Leo',
        sayName: function () {  // sayName函数在obj中定义
            console.log(this.name);
        }
    };
    obj.sayName(); // Leo,在obj中调用sayName,指向obj
    var foo = obj.sayName;  // 将sayName引用地址赋值给foo
    foo(); // Tom  独立调用sayName,this指向window
    var box = {
        name: 'Bob',
        say:foo // 将sayName引用地址赋值给say
    };
    box.say(); // Bob 在box中调用sayName,this指向box

分析一些例子

    // demo01
    function sayName() {
        // 'use strict';
        console.log(this.name)
    }
    function func(fn) {
        fn(); // 函数被传进来后独立调用
    }
    var name = 'Tom';
    var obj = {
        name: 'Leo',
        say: sayName // 函数sayName引用地址赋值给say
    };
    func(obj.say);  // Tom
    // 将sayName函数传入func函数,并调用sayName
    // 函数sayName独立调用,非严格模式时函数中的this为window
    // 使用严格模式时,this为undefined,执行this.name会报错

    // demo02
    var name = 'Tom';
    var obj = {
        name: 'Leo',
        func: function () {
            (function () {
                //'use strict'
                console.log(this.name);
            })();
        }
    }
    obj.func();//Tom
    // obj.func()调用时,内部自执行函数自动执行,没有调用者,this指向window
    // 使用严格模式时,this为undefined,执行this.name会报错

JavaScript提供了三种绑定this的方法:call、apply和bind。
call方法,第一个参数是this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该方法。
call方法的第一个参数应该是一个对象,如果参数为空、null、和undefined,则默认传入全局对象。
如果传入的第一参数是原始值,那么会自动转换成对应的包装类型,然后再传入call方法。
call第二个及以后的参数是函数调用时所需的参数。
apply方法和call方法类似,第一个参数也是this的指向。唯一区别是它接受一个数组作为函数执行时的参数。
apply/call方法不仅绑定函数执行时所在的对象,还会立即执行函数,因此要把绑定的语句写在函数体内。
bind方法将函数体内的this绑定到某个对象,然后每次返回一个新函数。
bind方法比apply/call方法更进一步,除了绑定this,还可以绑定原函数的参数。

    function fn(n, m) {
        console.log(this.a + n + m);
    }
    var obj = {
        a: 20
    }
    fn.call(obj, 100, 10); // 130
    fn.apply(obj, [20, 10]); // 50

    var arr = [8,3,4,1,5,9];
    console.log(Math.max.apply(null, arr)); // 9

    // 使用call/apply将arguments转换为数组, 返回结果为数组,arguments自身不会改变
    var arg = [].slice.call(arguments);
    //将DOM中的nodelist转换为数组
    [].slice.call( document.getElementsByTagName('li') );

    // 实现继承
    var Person = function (name) {
        this.name = name;
    }
    var Student = function (age) {
        this.age = age;
        Person.call(this, name);
    }
    Student.prototype.message = function () {
        console.log('name:'+ this.name+', age:'+this.age);
    }
    new Student('Leo', '26').message();

灵活使用this。

    var name = 'Tom';
    var obj = {
        name: 'Leo',
        sayName: function() {
            setTimeout(function() {
                console.log(this.name)
            }, 500)
        }
    }
    obj.sayName(); // Tom*/
    // 定时器中回调函数独立调用,this指向window
    // 要获取obj中的name
    // 方法1,使用一个变量,保存this
    var obj = {
        name: 'Leo',
        sayName: function() {
            var _this = this;
            setTimeout(function() {
                console.log(_this.name)
            }, 500)
        }
    }
    obj.sayName() // Leo
    // 方法2 使用bind (注意:若使用call/apply会立即执行回调函数)
    var obj = {
        name: 'Leo',
        sayName: function() {
            setTimeout(function() {
                console.log(this.name)
            }.bind(this), 500)
        }
    }
    obj.sayName() // Leo

参考资料:
《JavaScript高级程序设计》
《JavaScript 标准参考教程》
汤姆大叔-深入理解JavaScript系列

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

推荐阅读更多精彩内容