掌握 JavaScript 中的 this, call, apply 的原理

栏目: IT技术 · 发布时间: 4年前

内容简介:作者:达达前端 公号 / Jeskson(本文来自作者投稿)前言,为什么要学习在掌握JavaScript中的this,call,apply,因为面试官会问啊!所以我们 必须掌握才能答啊!那么this是什么,Function.prototype.call和

(给 前端大全 加星标,提升前端技能

作者:达达前端 公号 / Jeskson(本文来自作者投稿)

前言,为什么要学习在掌握JavaScript中的this,call,apply,因为面试官会问啊!所以我们 必须掌握才能答啊!那么this是什么,Function.prototype.call和

Function.prototype.apply这两个方法又是如何使用在JavaScript中的呢。

学习掌握this是必须的,我们常常在编写JavaScript中的代码时,会常用到它。

this的指针作用域,在全局环境中执行this,表示Global对象,在浏览器中表示window对象;当通过new运算符来调用函数时,函数被当做为一个构造函数,this的指向构造函数创建出来的对象;当在函数的执行环境中使用this时,情况有些不同,如函数没有作为一个非window对象的属性,那么只是定义了在这个函数,不管这个函数是不是定义在另一个函数中,其函数中的this仍表示为window对象;如果函数表示作为一个非window对象的属性,则表示函数中的this就代表为 这个对象。

掌握 JavaScript 中的 this, call, apply 的原理

如截图情况下,在全局执行环境中使用this,表示Global对象,在浏览器中表示为window对象。

掌握 JavaScript 中的 this, call, apply 的原理

function A(){

//在A函数中定义一个B函数

function B(){

console.log(this); //Window

console.log(typeof this); //object

console.log(this === window); //true

}

//在A函数内部调用B函数

B();

}

//调用A函数

A();

在函数执行环境中使用this时,如果函数没有明显的作为非window对象的属性,而只是定义了函数,不管这个函数是不是定义在另一个函数中,这个函数中的this仍然表示window对象。

掌握 JavaScript 中的 this, call, apply 的原理

//定义一个对象obj,添加属性name,添加方法objFun

var obj = {

name: 'dada',

objFun: function(){

console.log(this); // Object {name: "dada"}

console.log(typeof this); //object

console.log(this === window); //false

console.log(this.name); //dada

}

};

//调用obj对象的方法

obj.objFun(); //this 绑定到当前对象,也就是obj对象

掌握 JavaScript 中的 this, call, apply 的原理

//定义一个对象obj,添加属性name,添加方法objFun

var obj = {

name: 'dada',

objFun: function(){

console.log(this); //window

console.log(typeof this); //object

console.log(this === window); //true

console.log('dada的,名字'+this.name+'大帅哥');

}

};

var test = obj.objFun;

test();

可以看出函数内部中this值不是静态的,是动态的,可以改变的,每次调用一个函数时,它总是在重新求值。函数内部中的this值,实际上是由函数被调用的父作用域提供,依赖实际函数的语法。

// 第一种情况


//调用obj对象的方法

obj.objFun(); //this 绑定到当前对象,也就是obj对象


// 第二种情况


var test = obj.objFun;

test();

var test = obj.objFun

// 这里没有调用函数

test()

// 这里调用了函数


// test不是一个对象的引用,所以this值代表全局对象。

当通过new运算符来调用函数时,函数被当做一个构造函数,this指向构造函数创建出来的对象。

掌握 JavaScript 中的 this, call, apply 的原理

new创建出来了一个构造函数,这个时候this的值,指向构造函数创建出来的对象。

var name = 'dada';

function A(){

console.log(this.name);

}

A(); // dada

var B = new A(); //undefined (因为B并没有name属性)

VM162:3 dada

VM162:3 undefined

undefined

掌握 JavaScript 中的 this, call, apply 的原理

var name = 'windowdada';

var obj = {

name: 'objdada',

objB: {

name: 'objBdada',

bFun: function(){

console.log(this.name);

}

}

};


var test = obj.objB.bFun();


var test2 = obj.objB.bFun;

test2();


var test3 = obj.objB;


var test4 = test3.bFun;

test4();

掌握 JavaScript 中的 this, call, apply 的原理

掌握 JavaScript 中的 this, call, apply 的原理

注意()的近邻的左边,如果这个的左边是一个引用,那么传递给调用函数的this值为引用所属的这个对象,否则this指向为全局对象。

var test = obj.objB.bFun();

// ()左边是bFun引用,它指向objB这个对象,所有打印出objBdada

var test2 = obj.objB.bFun;

test2();

// ()的左边为test2,它不是某个对象的引用,所以是全局对象

// 打印出 objBdada

var test4 = test3.bFun;

test4();


// 同理这个也是

JavaScript中this的原理

掌握 JavaScript 中的 this, call, apply 的原理

掌握 JavaScript 中的 this, call, apply 的原理

var name = 'windowDada';

var obj = {

name: 'dada',

foo: function () {

console.log(this.name);

}

};


var foo = obj.foo;


// 写法一

obj.foo()


// 写法二

foo()

VM593:5 dada

VM593:5 windowDada

这个时候我相信你已经看懂了。this指向的是函数运行时所在的环境,对于obj.foo()来说,foo运行在obj环境中,所以这个时候的this指向为obj这个对象,对于foo()来说,foo运行是全局环境,这个this的指向为全局环境。(你会问为什么呢?一个指向obj这个对象,一个运行环境为全局环境,这里可以运用()左边方法)

对呀为什么呢?函数的运行环境是怎么决定在哪种情况的?

为什么obj.foo()的环境就在obj这个环境中,而作为

var foo = obj.foo,foo()的运行环境就变成了全局的执行环境呢?

this的指向设计,跟内存的数据结构有关。

var obj = {

name: 'dada'

};

当一个对象赋值给一个变量obj的时候,JavaScript引擎会在内存里,先生成一个对象为 { name: 'dada' },然后才把这个对象的内存地址赋值给这个变量 obj。

我们说过了很多很多遍了,都知道这个变量obj就是一个地址,这个时候如果要读 obj.foo,那么引擎就会从这个变量 obj中拿内存地址,然后再从这个地址 读取原始对象,返回它的foo属性。

注意:原始的对象(开始创建的对象 { name: 'dada' } )以字典结构保存的,每个属性名都对应一个属性描述对象。foo属性的值保存在属性描述对象的value属性里面。

this指包含它的函数作为方法被调用时所属的对象。

this,第一包,含它的函数,第二,作为方法被调用时,第三,所属的对象。

掌握 JavaScript 中的 this, call, apply 的原理

function da(){

console.log(this); //window

}

da();

会调用我,我就是谁的,谁最后调用我,我就是谁的。

掌握 JavaScript 中的 this, call, apply 的原理

testFunda()函数是在全局中被window对象所调用的,this的指向为window对象,而nameda变量在 testFun da 函数中,window对象中没有这个变量,所以打印不出来。

注意()的左边为testFunda

testFun da ()函数是在全局中被window对象所调用的哦!

因此this的指向就是window对象哦!

掌握 JavaScript 中的 this, call, apply 的原理

var namedada = 'dada'

function testFundada () {

var namedada="hello dada!";

console.log(this.namedada);

}

testFundada();

VM717:4 dada

看这个代码当然打印出的是dada啦,因为从全局调用,全局中有这个属性,就打印这个属性。

this被包含中一个函数中,但是这个函数被另个函数包含的情况下,这个this的指向为顶部的函数。

掌握 JavaScript 中的 this, call, apply 的原理

var obj={

a:"da",

b:function(){

var a="dada";

console.log(this.a);

}

};

obj.b();

VM726:5 da

this被包含在函数b()中,因为是被obj对象所调用的,所以这个this属于这个obj对象,打印出来的就是da这个字符串了。

谁最后调用我,我就属于谁!

掌握 JavaScript 中的 this, call, apply 的原理

var obj = {

a: 1,

b:{

fn:function(){

console.log(this.a); //undefined

}

}

};

obj.b.fn();


VM730:5 undefined

对象obj是在window上定义的,所以如下显示:

obj.b.fn()=window.obj.b.fn()

谁先调用我不算,谁最后调用我才算,window,那么this不是指向全局的对象了吗,但是最后的是被fn()调用,()左边为b对象,所以this就指向这个b对象了,因为函数中没有这个变量,所以为undefined。

出一道考题

掌握 JavaScript 中的 this, call, apply 的原理

结果是啥?我知道为2,你知道吗?那看看执行结果吧!

var obj = {

name: 1,

b:{

name: 2,

fn:function(){

var name = 3

console.log(this.name);

}

}

};

obj.b.fn();

掌握 JavaScript 中的 this, call, apply 的原理

函数情况,属性的值为一个函数

掌握 JavaScript 中的 this, call, apply 的原理

var obj = { foo: function () {} };

在JavaScript引擎中会将函数单独保存在内存中,再将函数的地址赋值给foo属性的value属性。

掌握 JavaScript 中的 this, call, apply 的原理

{

foo: {

[[value]]: 函数的地址

...

}

}

掌握 JavaScript 中的 this, call, apply 的原理

var f = function () {};

var obj = { f: f };


// 单独执行

f()


// obj 环境执行

obj.f()

掌握 JavaScript 中的 this, call, apply 的原理

var fda = function () {

console.log('da');

};


var objDada = { f: fda };


// 单独执行

fda()


// objDada 环境执行

objDada.fda()

VM858:2 da

环境的考虑,在JavaScript中运行在函数体内部,引用当前环境的其他变量。在JavaScript中,由于函数可以在不同的运行环境执行,就要一种机制,使能够在函数体内部获取当前的运行环境。

this的出现,目的在于就是指代函数当前的运行环境。

this 指代全局对象

function test(){

this.x = 1;

alert(this.x);

}

test(); // 1

this 指代上级对象

function test(){

alert(this.x);

}

var o = {};

o.x = 1;

o.m = test;

o.m(); // 1

this 指代 new 出的对象

var x = 3;


function test(){

this.x = 1;

}


var o = new test();


alert(x); // 3


alert(o.x); // 1

函数的不同使用场合,this 有不同的值,this是函数运行时所在的环境对象。

掌握 JavaScript 中的 this, call, apply 的原理

call的用法

call(thisObj,arg1,arg2,arg...)

调用一个对象的方法,以另一个对象替换当前对象,call方法用来代替另一个对象调用一个方法,该方法可以将一个函数对象的上下文改变为由this obj指定的新对象。

call方法的参数,如果是不传,或是null,undefined的情况下,函数中的this指向就是指window对象,如果传递的是另一个函数的函数名,函数中的this指向就是这个函数的引用,如果参数传递的是基本类型数据时,函数中的this指向就是其对应的 包装对象了,如果参数传递的是一个对象时,函数中的this就指向这个对象。

一个函数的函数名,函数名是引用,所以指向是指这个函数的引用

一个对象,所以this就指向这个对象

基本类型数据,就指向这个包装对象

Function.prototype.call(thisArg[,arg1[,arg2, ...]])

当以thisArg和可选择的arg1,arg2等等作为参数在一个func对象上调用call方法。

掌握 JavaScript 中的 this, call, apply 的原理

掌握 JavaScript 中的 this, call, apply 的原理

var da = {

name: "da",

sayHello: function (age) {

console.log("hello, i am ", this.name + " " + age + " years old");

}

};


var jeskson = {

name: "jeskson",

};


da.sayHello(12);

VM891:4 hello, i am da 12 years old

undefined

da.sayHello.call(jeskson,13);

VM891:4 hello, i am jeskson 13 years old

undefined

掌握 JavaScript 中的 this, call, apply 的原理

掌握 JavaScript 中的 this, call, apply 的原理

掌握 JavaScript 中的 this, call, apply 的原理

在JavaScript中,call和apply作用是一样的

为了改变某个函数运行时的上下文(context)而存在的,就是为了改变函数体内部this的指向。

每个函数都包含两个非继承而来的方法:

call()和apply()

apply的用法

掌握 JavaScript 中的 this, call, apply 的原理

apply(thisObj,argArray)

apply方法应用于某一个对象的一个方法

用另一个对象替换当前对象。

区别:参数书写方式不同

call() 方法分别接受参数。

apply() 方法接受数组形式的参数。

Math.max(1,2,3); // 会返回 3


Math.max.apply(null, [1,2,3]); // 也会返回 3


Math.max.apply(Math, [1,2,3]); // 也会返回 3


Math.max.apply(" ", [1,2,3]); // 也会返回 3


Math.max.apply(0, [1,2,3]); // 也会返回 3

call(thisObj, arg1, arg2, arg3, arg4);

apply(thisObj, [args]);


thisObj:


callapply第一个参数是一样的

该参数将替代Function类里面的this对象


arg1,arg2....


是一个个的参数


args

一个数组或类数组,是一个参数列表

掌握 JavaScript 中的 this, call, apply 的原理

JavaScript 严格模式

如果 apply() 方法的第一个参数不是对象,它将成为被调用函数的所有者(对象)。

在“非严格”模式下,它成为全局对象。

参考:

http://www.ruanyifeng.com/blog/2018/06/javascript-this.html

觉得本文对你有帮助?请分享给更多人

关注「前端大全」加星标,提升前端技能

掌握 JavaScript 中的 this, call, apply 的原理

好文章,我 在看 :heart:


以上所述就是小编给大家介绍的《掌握 JavaScript 中的 this, call, apply 的原理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Twenty Lectures on Algorithmic Game Theory

Twenty Lectures on Algorithmic Game Theory

Tim Roughgarden / Cambridge University Press / 2016-8-31 / USD 34.99

Computer science and economics have engaged in a lively interaction over the past fifteen years, resulting in the new field of algorithmic game theory. Many problems that are central to modern compute......一起来看看 《Twenty Lectures on Algorithmic Game Theory》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具