Apakah ini? Artikel berikut akan memperkenalkan anda kepada ini dalam JavaScript, dan bercakap tentang perbezaan antara ini dalam kaedah panggilan yang berbeza fungsi saya harap ia akan membantu anda!
dalamJavaScript
this
adalah berbeza terutamanya, Java
dalam bahasa this
tidak boleh ditukar semasa fasa pelaksanaan kod. , manakala JavaScript this
terikat dalam fasa panggilan . Kerana harta ini, ia memberi this
banyak ruang untuk bermain. Tetapi ia agak berbeza dalam mod ketat dan mod tidak ketat, dan kaedah panggilan fungsi yang berbeza juga membawa kepada beberapa perbezaan dalam hal ini.
Tentukan dahulu ini: Ini ialah pembolehubah yang ditentukan apabila konteks pelaksanaan dibuat yang tidak boleh diubah semasa pelaksanaan.
Apa yang dipanggil konteks pelaksanaan ialah enjin JavaScript yang akan menggunakan beberapa pembolehubah dan fungsi sebelum melaksanakan sekeping kod . , ini ialah proses yang diisytiharkan terlebih dahulu dan kemudian disimpan dalam objek berubah. 'Coretan kod' ini termasuk: kod global (kod dalam teg skrip), kod dalaman fungsi, kod dalaman eval. Rantaian skop yang kita kenali juga akan disimpan di sini, disimpan dalam bentuk seperti tatasusunan dalam atribut [[Skop]] bagi fungsi yang sepadan.
Ini hanya ditentukan semasa fasa panggilan fungsi, iaitu, apabila konteks pelaksanaan dibuat, ia ditetapkan dan disimpan dalam objek berubah. Ciri ini juga membawa kepada kebolehubahan ini: iaitu, apabila fungsi dipanggil dengan cara yang berbeza, nilai ini mungkin berbeza.
Seperti yang kami katakan di atas, ini berkelakuan berbeza dalam mod ketat dan mod tidak ketat:
var a = 1; function fun() { 'use strict'; var a = 2; return this.a; } fun();//报错 Cannot read property 'a' of undefined
Dalam mod ketat, ini menunjukkan kepada tidak ditentukan;
var a = 1; function fun() { var a = 2; return this.a; } fun();//1
Dalam mod tidak ketat ini menghala ke tetingkap
Sebab mengapa sekeping kod yang sama di atas wujud; dalam mod yang berbeza Persembahan yang berbeza adalah disebabkan oleh perbezaan antara ini dalam mod ketat dan mod tidak ketat.
Kesimpulan: Apabila fungsi dipanggil secara bebas, ini menunjukkan kepada tidak ditentukan dalam mod ketat, apabila ini menunjuk kepada tidak ditentukan, ia secara automatik menghala ke objek global (iaitu,. dalam tetingkap penyemak imbas)
Seperkara lagi, dalam persekitaran global, ini menunjukkan kepada dirinya sendiri:
this.a = 1; var b = 1; c = 1; console.log(this === window)//true //这三种都能得到想要的结果,全局上下文的变量对象中存在这三个变量
Seperkara lagi, apabila ini. tidak digunakan dalam fungsi Apa yang akan berlaku? Lihat contoh:
var a = 1000; var obj = { a: 1, b: this.a + 1 } function fun() { var obj = { a: 1, c: this.a + 2 //严格模式下这块报错 Cannot read property 'a' of undefined } return obj.c; } console.log(fun());//1002 console.log(obj.b);//1001
Dalam kes ini, ini masih menunjuk ke tetingkap. Kemudian kita boleh membuat kesimpulan yang berasingan:
Apabila obj diisytiharkan secara global, ini dalam atribut dalaman obj menunjuk ke objek global Apabila obj diisytiharkan dalam fungsi, dalam mod ketat ini akan Points kepada mod yang tidak ditentukan dan tidak ketat secara automatik menukar kepada menunjuk ke objek global.
Baiklah, saya baru sahaja mencubanya, dan saya tahu perbezaan antara mod ini dalam mod ketat dan tidak ketat Walau bagaimanapun, penggunaan yang paling biasa dalam kehidupan seharian kita adalah menggunakan ini Saya juga menyebut perkara ini di atas. Terdapat perbezaan dalam kaedah panggilan fungsi yang berbeza. Empat jenis:
dikembangkan pada empat situasi masing-masing:
Contoh di atas sebenarnya adalah panggilan langsung, tetapi Saya Memutuskan untuk menulis contoh lain:
var a = 1; var obj = { a: 2, b: function () { function fun() { return this.a } console.log(fun()); } } obj.b();//1
Walaupun fungsi keseronokan ditakrifkan dalam kaedah obj.b, ia masih merupakan fungsi biasa Apabila dipanggil terus, ia menunjuk kepada tidak ditentukan dalam mod tidak ketat dan secara automatik menunjuk kepada objek global Seperti yang dijangkakan, mod ketat akan melaporkan ralat undefined.a tidak ditubuhkan dan a tidak ditakrifkan.
Perkara penting untuk diperkatakan sekali lagi: Apabila fungsi dipanggil secara bebas, ini menunjukkan kepada undefined dalam mod ketat, apabila ini menunjuk ke undefined, ia secara automatik menghala ke global objek ( Dalam pelayar, ia adalah tetingkap).
var a = 1; var obj = { a: 2, b: function() { return this.a; } } console.log(obj.b())//2
Fungsi tanpa nama yang dirujuk oleh b dipanggil sebagai kaedah obj kepada objek yang memanggilnya. Ini adalah obj. Jadi bagaimana jika kaedah b tidak dipanggil sebagai kaedah objek? Apakah maksudnya? Ia seperti ini:
var a = 1; var obj = { a: 2, b: function() { return this.a; } } var t = obj.b; console.log(t());//1
Seperti di atas, hasil pelaksanaan fungsi t ternyata menjadi pembolehubah global 1. Mengapa? Ini melibatkan ruang memori Javascript Maksudnya, atribut b objek obj menyimpan rujukan kepada fungsi tanpa nama, yang boleh difahami sebagai penunjuk. Apabila memberikan nilai kepada t, ia tidak membuka ruang memori yang berasingan untuk menyimpan fungsi baharu Sebaliknya, t menyimpan penunjuk yang menunjuk ke fungsi ini. Ia sama dengan melaksanakan sekeping kod pseudo ini:
var a = 1; function fun() {//此函数存储在堆中 return this.a; } var obj = { a: 2, b: fun //b指向fun函数 } var t = fun;//变量t指向fun函数 console.log(t());//1
Pada masa ini, t ialah penunjuk kepada fungsi keseronokan Panggilan t adalah bersamaan dengan memanggil keseronokan secara langsung secara semula jadi mudah difahami.
关于apply和call是干什么的怎么用本文不涉及,请移驾:apply,call
这是个万能公式,实际上上面直接调用的代码,我们可以看成这样的:
function fun() { return this.a; } fun();//1 //严格模式 fun.call(undefined) //非严格模式 fun.call(window)
这时候我们就可以解释下,为啥说在非严格模式下,当函数this指向undefined的时候,会自动指向全局对象,如上,在非严格模式下,当调用fun.call(undefined)的时候打印出来的依旧是1,就是最好的证据。
为啥说是万能公式呢?再看函数作为对象的方法调用:
var a = 1; var obj = { a: 2, b: function() { return this.a; } } obj.b() obj.b.call(obj)
如上,是不是很强大,可以理解为其它两种都是这个方法的语法糖罢了,那么apply和call是不是真的万能的呢?并不是,ES6的箭头函数就是特例,因为箭头函数的this不是在调用时候确定的,这也就是为啥说箭头函数好用的原因之一,因为它的this固定不会变来变去的了。关于箭头函数的this我们稍后再说。
何为构造函数?所谓构造函数就是用来new对象的函数,像Function
、Object
、Array
、Date
等都是全局定义的构造函数。其实每一个函数都可以new对象,那些批量生产我们需要的对象的函数就叫它构造函数罢了。注意,构造函数首字母记得大写。
function Fun() { this.name = 'Damonre'; this.age = 21; this.sex = 'man'; this.run = function () { return this.name + '正在跑步'; } } Fun.prototype = { contructor: Fun, say: function () { return this.name + '正在说话'; } } var f = new Fun(); f.run();//Damonare正在跑步 f.say();//Damonare正在说话
如上,如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象。为啥呢?new做了啥呢?
伪代码如下:
function Fun() { //new做的事情 var obj = {}; obj.__proto__ = Fun.prototype;//Base为构造函数 obj.name = 'Damonare'; ...//一系列赋值以及更多的事 return obj }
也就是说new做了下面这些事:
也就是说new其实就是个语法糖,this之所以指向临时对象还是没逃脱上面说的几种情况。
当然如果直接调用Fun(),如下:
function Fun() { this.name = 'Damonre'; this.age = 21; this.sex = 'man'; this.run = function () { return this.name + '正在跑步'; } } Fun(); console.log(window)
其实就是直接调用一个函数,this在非严格模式下指向window,你可以在window对象找到所有的变量。
另外还有一点,prototype对象的方法的this指向实例对象,因为实例对象的__proto__
已经指向了原型函数的prototype。这就涉及原型链的知识了,即方法会沿着对象的原型链进行查找。
刚刚提到了箭头函数是一个不可以用call和apply改变this的典型。
我们看下面这个例子:
var a = 1; var obj = { a: 2 }; var fun = () => console.log(this.a); fun();//1 fun.call(obj)//1
以上,两次调用都是1。
那么箭头函数的this是怎么确定的呢?箭头函数会捕获其所在上下文的 this
值,作为自己的 this
值,也就是说箭头函数的this在词法层面就完成了绑定。apply,call方法只是传入参数,却改不了this。
var a = 1; var obj = { a: 2 }; function fun() { var a = 3; let f = () => console.log(this.a); f(); }; fun();//1 fun.call(obj);//2
如上,fun直接调用,fun的上下文中的this值为window,注意,这个地方有点绕。fun的上下文就是此箭头函数所在的上下文,因此此时f的this为fun的this也就是window。当fun.call(obj)再次调用的时候,新的上下文创建,fun此时的this为obj,也就是箭头函数的this值。
再来一个例子:
function Fun() { this.name = 'Damonare'; } Fun.prototype.say = () => { console.log(this); } var f = new Fun(); f.say();//window
有的同学看到这个例子会很懵逼,感觉上this应该指向f这个实例对象啊。不是的,此时的箭头函数所在的上下文是__proto__
所在的上下文也就是Object函数的上下文,而Object的this值就是全局对象。
那么再来一个例子:
function Fun() { this.name = 'Damonare'; this.say = () => { console.log(this); } } var f = new Fun(); f.say();//Fun的实例对象
如上,this.say所在的上下文,此时箭头函数所在的上下文就变成了Fun的上下文环境,而因为上面说过当函数作为构造函数调用的时候(也就是new的作用)上下文环境的this指向实例对象。
【相关推荐:javascript学习教程】
Atas ialah kandungan terperinci Apa ini? Analisis mendalam tentang ini dalam JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!