JavaScript中this的使用

js中this的四种用法

参考博文
JavaScript中this的四个绑定规则总结

在JavaScript中每一个函数都是一个对象,所以在这个函数中, var temp = this,指的是当前对象
this是一个关键字,它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用
在 ES6 的箭头函数下, call 和 apply 将失效,

this在函数执行时,this 总是指向调用该函数的对象。要判断 this 的指向,其实就是判断 this 所在的函数属于谁。在《javaScript语言精粹》这本书中,把 this 出现的场景分为四类,简单的说就是:

  • 有对象就指向调用者
  • 没对象指向全局对象
  • new 出来的 指向新对象
  • call/bind/apply来改变this的指向

1. 有对象就指向调用者 (隐式绑定)

函数有所属对象的时候,通过 . 表达式调用,这时 this自然指向所属对象,

var obj = {
    value: 100,
    getValue: function() {
        console.log(this.value) // 这里this 就是obj对象
        return this.value
    }
}
var fn = obj.getValue

console.log(obj.getValue())  ===> 100
console.log(fn()) ===> undefined

<!-- getValue() 属于对象 myObject,并由 myOjbect 进行 . 调用,因此 this 指向对象 myObject。 -->

2. 函数没有所属对象:指向全局对象 (默认绑定)

var value = 'global'

var obj = {
    value: 100
}

obj.getValue = function() {
    var foo = function() {
        console.log(this.value) // 'global' ,var 声明的默认为全局变量,所以这里访问的是全局的, 严格模式下为undefined
        console.log(this) // 全局对象global  window
    }
    foo()
    
    return this.value;
}
<!-- 
 在上述代码块中,foo 函数虽然定义在 getValue 的函数体内,
 但实际上它既不属于 getValue 也不属于 myObject。
 foo 并没有被绑定在任何对象上,所以当调用时,它的 this 指针指向了全局对象 global。
 
 据说这是个设计错误。
 -->

3. 构造器中的this 指向新对象 (new 绑定)

js 中,我们通过 new 关键词来调用构造函数,此时 this 会绑定在该新对象上。

let Dog = function() {
    this.name = '旺财'
}

let dog1 = new Dog()

console.log(dog1.name)

===> 旺财


<!-- 
顺便说一句,在 js 中,构造函数、普通函数、对象方法、闭包,这四者没有明确界线。界线都在人的心中。 
 -->

4. apply 和 call 调用以及 bind 绑定:指向绑定的对象 (显示绑定)

  • apply方法接受两个参数, 第一个是函数运行的作用域, 第二个是函数的参数数组(arguments)
  • call方法第一个参数的意义与 apply() 方法相同,只是其他的参数需要一个个列举出来。
  • bind

简单来说,call 的方式更接近我们平时调用函数,而 apply 需要我们传递 Array 形式的数组给它。它们是可以互相转换的。

var myObject = {value: 100};
 
var foo = function(){
 console.log(this.value);
};
 
foo();                       // ===> undefined
foo.apply(myObject);  ===> 100  // { value: 100 }
foo();                       // ===> undefined
foo.call(myObject);     ===> 100  // { value: 100 }
foo();                       // ===> undefined
 
var newFoo = foo.bind(myObject);
newFoo(); // { value: 100 }

优先级

new绑定 > 显示绑定 > 隐式绑定 > 默认绑定

关于call/apply/bind的区别与用法

call,apply,bind比较

  1. call

call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。

var obj = {
    message: 'My name is: '
}

function getName(firstName, lastName) {
    console.log(this.message + firstName + ' ' + lastName)
}

getName.call(obj, 'Dot', 'Dolby') 
====> My name is: Dot Dolby
  1. apply

apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。

var obj = {
    message: 'My name is: '
}

function getName(firstName, lastName) {
    console.log(this.message + firstName + ' ' + lastName)
}

getName.apply(obj, ['Dot', 'Dolby'])// My name is: Dot Dolby
====> My name is: Dot Dolby
  1. bind

和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。

var obj = {
    name: 'Dot'
}

function printName() {
    console.log(this.name)
}

var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot()  // Dot

ES5 实现继承 通过call或apply修改this指向

var Person1  = function () {
    this.name = 'Dot';
}
var Person2 = function () {
    this.getname = function () {
        console.log(this.name);
    }
    Person1.call(this);
}
var person = new Person2();
person.getname();       // Dot

Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。

参数的使用

call 是把第二个及以后的参数作为 fn 方法的实参传进去,而 fn1 方法的实参实则是在 bind 中参数的基础上再往后排

function fn(a, b, c) {
    console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');

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

推荐阅读更多精彩内容