Heim  >  Artikel  >  Web-Frontend  >  Detailliertes Verständnis dieses Zeigers in Javascript

Detailliertes Verständnis dieses Zeigers in Javascript

小云云
小云云Original
2018-03-17 16:21:101571Durchsuche

Dieser Artikel vermittelt Ihnen hauptsächlich ein tiefgreifendes Verständnis dieses Zeigers in JavaScript. Wenn dieser in Java falsch verwendet wird, meldet idea direkt einen Fehler!

Zum Beispiel...



In der objektorientierten Programmierung dort Es gibt zwei wichtige Konzepte: Eines ist eine Klasse und das andere ist ein instanziiertes Objekt. Eine Klasse ist ein abstraktes Konzept: Eine Klasse ist wie eine Form, und instanziierte Objekte werden durch diese Form hergestellt Für hergestellte Produkte sind instanziierte Objekte die realen Dinge, die wir benötigen. Klassen und instanziierte Objekte sind jedoch eng miteinander verbunden, aber die Funktionen von Klassen können instanziierte Objekte nicht ersetzen, ebenso wie Formen und Formen der beiden sind unterschiedlich.

Aus dem obigen Code können wir ersehen, dass der This-Zeiger nur in instanziierten Objekten in der Java-Sprache verwendet werden kann. Der This-Zeiger ist gleich dem instanziierten Objekt und der Punktoperator wird danach hinzugefügt Nach dem Operator steht, was dieser hat, wie zum Beispiel: Name, Beruf, Hände, Füße usw.

TatsächlichDas logische Konzept dieses Zeigers in Javascript ist auch ein instanziiertes Objekt Dies stimmt mit dem This-Zeiger in der Java-Sprache überein, aber der This-Zeiger in Javascript unterscheidet sich von dem in Java. Das ist meiner Meinung nach aus drei grundlegenden Gründen:

Grund 1: Das Merkwürdige ist, dass es auch diesen Zeiger hat dass dies eine objektorientierte Sprache ist. Genauer gesagt ist die Funktion in der Programmiersprache eine Funktion höherer Ordnung Gleichzeitig kann die Funktion in JavaScript auch als Konstruktor verwendet werden. Diese Konstruktfunktionen können instanziierte Objekte erstellen. Daher ändert sich der Zeiger dieses Zeigers weiterhin, wenn die Methode ausgeführt wird, was schwer zu kontrollieren ist.

Grund 2: Der globale Gültigkeitsbereich in JavaScript hat einen großen Einfluss auf den This-Zeiger. Aus dem obigen Java-Beispiel können wir ersehen, dass der This-Zeiger nur nach Verwendung des New geändert werden kann Der Operator wird wirksam, aber in JavaScript wird er auch wirksam, ohne dass eine neue Operation ausgeführt wird. Zu diesem Zeitpunkt verweist er häufig auf das globale Objektfenster.

Grund 3: Die Call- und Apply-Operatoren in JavaScript können den Zeiger nach Belieben ändern. Dies scheint sehr flexibel zu sein, aber dieser unvernünftige Ansatz zerstört unser Verständnis der ursprünglichen Bedeutung dieses Zeigers und macht es auch schwierig Code schreiben. Es ist schwer zu verstehen, worauf dies wirklich hinweist



Die oben genannten drei Gründe verstoßen alle gegen die Bei der traditionellen Verwendung dieses Zeigers haben alle Methoden ein anderes Verständnis als das traditionelle Prinzip, und in der tatsächlichen Entwicklung sind die drei Gründe oft miteinander verflochten, also liegt alles in den Wolken ...


Einführungsbuch: Professionelles Javascript für Webentwickler, - die erweiterte Version lautet:

dies zeigt immer auf die aufrufende Methode Object !



var name="zhoulujun";

function say(){

console.log(this.name)

}

say(); //zhoulujun



Im Skript-Tag können wir diesen Zeiger direkt verwenden , dieser Zeiger (der auf das Fensterobjekt zeigt, das Ergebnis) ist das Fensterobjekt , sie sind gleich, auch wenn das dreifache Gleichheitszeichen verwendet wird. Der globale Bereich beeinträchtigt häufig unser Verständnis der Funktionen der JavaScript-Sprache. Der Kern dieser Störung ist:

In der JavaScript-Sprache kann der globale Bereich als Fensterobjekt verstanden werden. Denken Sie daran, dass Window ein Objekt und keine Klasse ist, was bedeutet, dass Window ein instanziiertes Objekt ist. Dieser Instanziierungsprozess wird von der JavaScript-Engine abgeschlossen, wenn die Seite geladen wird. Die Elemente auf der gesamten Seite werden in diesem Fenster zusammengefasst Da Programmierer diesen Instanziierungsprozess nicht über Programmiersprachen steuern und steuern können, haben wir nicht das Gefühl, diesen Zeiger während der Entwicklung zu erstellen, und ignorieren ihn häufig. Dies beeinträchtigt unser Verständnis der Tatsache, dass dieser Zeiger auf das Fenster im Objekt zeigt Code-Situation.

Hier zeigt dies auf das Fensterobjekt, also this.name->zhoulujun!



Beim Ausführen der Say-Funktion erstellt JavaScript einen Execute-Kontext (Ausführungskontext), der alle während der Laufzeit der Say-Funktion benötigten Informationen enthält. Der Ausführungskontext verfügt auch über eine eigene Bereichskette. Wenn die Funktion ausgeführt wird, initialisiert die JavaScript-Engine mithilfe der Funktion say zunächst die Bereichskette des Ausführungskontexts.

Hier könnt ihr euch grob merken:

var myObj={
name:"zhoulujun",
fn:function(){
console.log(this.name)
}
};
myObj.fn();



这里的this指向obj,因为fn()运行在obj里面……

然后再来看……

var name="zhoulujun";
function say(){
console.log(this.name)
console.log(this)
}
say();
function say2(){
var site="zhoulujun.cn";
console.log(this.site);
}
say2();


myObj2={
site:"zhoulujun.cn",
fn:function(){
console.log(this.site)
}
}



这里的this指向的是对象myObj2,因为你调用这个fn是通过myObj2.fn()执行的,那自然指向就是对象myObj2,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个

然后,我们更深入(受不了 …………

myObj3={
site:"zhoulujun.cn",
andy:{
site:"www.zhoulujun.cn",
fn:function(){
console.log(this.site)
}
}
};
myObj3.andy.fn();



这里同样也是对象Object点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。

如果,你实在理解不了,就这么样背下来吧!

情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。

情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,如果不相信,那么接下来我们继续看几个例子。

这样既对了吗??深入点(就受不了了……讨厌……

myObj3={
site:"zhoulujun.cn",
andy:{
site:"www.zhoulujun.cn",
fn:function(){
console.log(this)
console.log(this.site)
}
}
};
//    myObj3.andy.fn();
var fn=myObj3.andy.fn;
fn();



其实,这里的 fn等价于

fn:function(age){

console.log(this.name+age);

}

下面我们来聊聊函数的定义方式:声明函数和函数表达式

我们最上面第一个案例定义函数的方式在javascript语言称作声明函数,第二种定义函数的方式叫做函数表达式,这两种方式我们通常认为是等价的,但是它们其实是有区别的,而这个区别常常会让我们混淆this指针的使用,我们再看看下面的代码:



Warum kann say ausgeführt werden, say3 jedoch nicht? Das liegt daran:



Warum ist das Druckergebnis von say3 undefiniert? Ich habe im vorherigen Artikel erwähnt, dass undefiniert ist Der Stapelbereich des Speichers hat bereits den Namen der Variablen, aber es gibt keinen Variablenwert im Stapelbereich. Gleichzeitig gibt es kein bestimmtes Objekt im Heap-Bereich. Dies liegt daran Die JavaScript-Engine scannt Variablendefinitionen während des Vorladens, aber das Druckergebnis von ftn01 ist sehr überraschend, da die vollständige Funktionsdefinition ausgedruckt und der Code nicht in der richtigen Reihenfolge ausgeführt wird, kann dies nur ein Problem erklären:

In In der JavaScript-Sprache werden Funktionen durch Deklaration von Funktionen definiert, und die JavaScript-Engine befindet sich im Vorverarbeitungsprozess. Hier werden die Funktionen der Vorverarbeitung in JavaScript hinzugefügt Im vorherigen Artikel habe ich erwähnt, dass es zwei Haupttypen von Ausführungsumgebungen gibt: globale Ausführungsumgebung und lokale Ausführungsumgebung. Tatsächlich wird dieser Prozess durch Kontextvariablen wiedergegeben. Die Vorverarbeitung ist eine weitere Möglichkeit, die Ausführungsumgebung zu erstellen. Kurz gesagt besteht der Hauptzweck der Vorverarbeitung und des Aufbaus der Ausführungsumgebung darin, die Variablendefinition zu klären und die Grenzen von Variablen zu unterscheiden. Es gibt jedoch einige Unterschiede bei der Deklaration von Funktionen während der globalen Bereichskonstruktion Durch die Vorverarbeitung globaler Variablen werden Variablendefinitions- und Zuweisungsvorgänge gleichzeitig abgeschlossen, sodass wir die laufenden Ergebnisse des obigen Codes sehen. Da die deklarierten Funktionen während der globalen Bereichskonstruktion abgeschlossen werden, sind die deklarierten Funktionen alle Attribute des Fensterobjekts. Dies erklärt, warum die deklarierte Funktion letztendlich zum Fensterobjekt gehört, egal wo wir sie deklarieren.

Es empfiehlt sich, hier einen Blick darauf zu werfen – die Ausführungsreihenfolge einer Java-Klasse:

http://www.zhoulujun.cn/zhoulujun/html/java/javaBase/7704.html



其实在javascript语言里任何匿名函数都是属于window对象,它们也都是在全局作用域构造时候完成定义和赋值,但是匿名函数是没有名字的函数变量,但是在定义匿名函数时候它会返回自己的内存地址,如果此时有个变量接收了这个内存地址,那么匿名函数就能在程序里被使用了,因为匿名函数也是在全局执行环境构造时候定义和赋值,所以匿名函数的this指向也是window对象,所以上面代码执行时候fn的this都是指向window,因为javascript变量名称不管在那个作用域有效,堆区的存储的函数都是在全局执行环境时候就被固定下来了,变量的名字只是一个指代而已。

类似的情况(面试题喜欢这么考!)……比如:



this都是指向实例化对象,前面讲到那么多情况this都指向window,就是因为这些时候只做了一次实例化操作,而这个实例化都是在实例化window对象,所以this都是指向window。我们要把this从window变成别的对象,就得要让function被实例化,那如何让javascript的function实例化呢?答案就是使用new操作符。

再来看 构造函数:

function  User(){
this.name="zhoulujun";
console.log(this);
}
var andy=new User();
console.log(andy.name)



why andy 的name  是 zhoulujun,那是:因为:

new关键字可以改变this的指向,将这个this指向对象andy,

那andy什么时候又成了思密达,oh,no,is Object?

Weil die Verwendung des Schlüsselworts new darin besteht, eine Objektinstanz zu erstellen (wichtige Dinge dreimal im Stillen lesen)

Hier verwenden wir die Variable andy, um eine Benutzerinstanz zu erstellen (entspricht dem Kopieren). Eine Kopie von User in das Objekt andy. Zu diesem Zeitpunkt wird es nur erstellt und nicht ausgeführt. Das Objekt, das diese Funktion aufruft, ist das Objekt andy. Warum gibt es also einen Namen? Das Objekt User? Weil Sie bereits eine Kopie der User-Funktion in das Objekt kopiert haben. Die Verwendung des neuen Schlüsselworts entspricht dem Kopieren einer Kopie.

Java-Programmierer: Klasse user=new User(); kommt mir bekannt vor...



Funktion ist sowohl eine Funktion als auch ein Objekt. Wenn Funktion eine Funktion ist, kann sie auch als Konstruktor von Javascript Ich denke oft, dass Klassen und Konstruktoren in einem zusammengefasst sind. Natürlich gibt es in der JavaScript-Sprachspezifikation kein Klassenkonzept, aber nach meinem Verständnis ist das möglich als Konstruktoren und gewöhnliche Funktionen verwendet werden. Ein Unterschied, der leichter zu verstehen ist . Nachfolgend veröffentliche ich die Erklärung des neuen Operators in „Erweiterte JavaScript-Programmierung“:

Der neue Operator führt zu folgenden Änderungen am Konstruktor:

1 . Erstellen Sie ein neues Objekt.

2. Weisen Sie dem neuen Objekt den Gültigkeitsbereich zu 🎜>3. Führen Sie den Code im Konstruktor aus (fügen Sie Attribute zu diesem neuen Objekt hinzu);

4.       返回新对象

……

妈的:读的那么拗口,不明觉厉…………看图……还不

不明白……

var myObj5={
name:"andy"
};
var myObj6=new Object();
myObj6.name="andy";
function  say5(name){
console.log(name)
}
var say6=new Function("name","console.log(name)");
console.log(myObj5)
console.log(myObj6)
say5("andy");
say6("andy");



还不明白,就请奶奶买块豆腐,撞死算了……

第四点也要着重讲下,记住构造函数被new操作,要让new正常作用最好不能在构造函数里写return,没有return的构造函数都是按上面四点执行,有了return情况就复杂了

return这王八蛋……



那么我这样呢……



does it have to be like this?Tell me why(why),is there something I have missed?

Tell me why(why),cos I don't understand…………



那是因为……because of u?no  return……



所以:如果返回的是基本类型,就会丢掉…只能返回Object类型……typeof  xx ===“object”

看到called 没有?什么鬼!!

其实new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。

var a={
name:"andy",
site:"zhoulujun.cn",
fn:function(age){
console.log(this.name+age);
}
};
var b={
name:"zhoulujun",
site:"www.zhoulujun.cn",
fn:function(age){
console.log(this.name+age);
}
};
a.fn(2); //andy2
a.fn.call(b,2) //zhoulujun2
a.fn.apply(b,[2])//zhoulujun2
当然,还有bind……
var arr = [1, 2];
var add = Array.prototype.push.bind(arr, 3);
// effectively the same as arr.push(3)
add();
// effectively the same as arr.push(3, 4)
add(4);
console.log(arr);
// <- [1, 2, 3, 3, 4]
在下面的例子,this将无法在作用域链中保持不变。这是规则的缺陷,并且常常会给业余开发者带来困惑。
function scoping () {
console.log(this);
return function () {
console.log(this);
};
}
scoping()();
// <- Window
// <- Window
有一个常见的方法,创建一个局部变量保持对this的引用,并且在子作用域中不能有同命变量。子作用域中的同名变量将覆盖父作用域中对this的引用。
function retaining () {
var self = this;
return function () {
console.log(self);
};
}
retaining()();
// <- Window
除非你真的想同时使用父作用域的this,以及当前this值,由于某些莫名其妙的原因,我更喜欢是使用的方法.bind函数。这可以用来将父作用域的this指定给子作用域。
function bound () {
return function () {
console.log(this);
}.bind(this);
}
bound()();
// <- Window

写到这里,都看不下去,逻辑有点混乱,有的是从前辈哪里引用的。

改天有时间整理下,然后,在去讲下闭包(……closer





Das obige ist der detaillierte Inhalt vonDetailliertes Verständnis dieses Zeigers in Javascript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn