Maison  >  Article  >  interface Web  >  Sept questions et réponses aux questions d'entretien JavaScript qui sont facilement négligées_Compétences Javascript

Sept questions et réponses aux questions d'entretien JavaScript qui sont facilement négligées_Compétences Javascript

WBOY
WBOYoriginal
2016-05-16 15:15:391364parcourir

Cette question est la dernière d'une série de questions d'entretien préliminaires que j'ai posées. Elle est utilisée pour tester les capacités JavaScript complètes de l'intervieweur. Malheureusement, au cours des deux dernières années, presque personne n'a été en mesure de répondre. C'est difficile simplement parce que la plupart des intervieweurs le sous-estiment.

Le sujet est le suivant :

function Foo() {
 getName = function () { alert (1); };
 return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

La réponse est :

function Foo() {
 getName = function () { alert (1); };
 return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//答案:
Foo.getName();//2
getName();//4
Foo().getName();//1
getName();//1
new Foo.getName();//2
new Foo().getName();//3
new new Foo().getName();//3

Cette question est basée sur mon expérience précédente en développement et les différents pièges que j'ai rencontrés en JS. Cette question implique de nombreux points de connaissance, notamment la promotion de la définition des variables, le pointage de ce pointeur, la priorité de l'opérateur, le prototype, l'héritage, la pollution des variables globales, la priorité des attributs d'objet et des attributs de prototype, etc.

Cette question contient 7 questions, veuillez les expliquer ci-dessous.

Première question

Regardons d'abord ce que nous avons fait dans la première moitié de cette question. Nous avons d'abord défini une fonction appelée Foo, puis créé une propriété statique appelée getName pour Foo pour stocker une fonction anonyme, puis créé un nouvel objet prototype pour Foo. . Une fonction anonyme appelée getName. Ensuite, une fonction getName est créée via l'expression de variable de fonction, et enfin une fonction getName est déclarée.

La première question, Foo.getName, accède naturellement aux propriétés statiques stockées sur la fonction Foo, qui vaut naturellement 2. Il n'y a rien à dire.

Deuxième question

La deuxième question est d'appeler directement la fonction getName. Puisqu'il est appelé directement, il accède à la fonction appelée getName dans la portée actuelle ci-dessus, cela n'a donc rien à voir avec 1 2 3. De nombreux enquêteurs ont répondu à cette question par 5. Il y a deux pièges ici, l'un est la promotion de la déclaration de variable et l'autre est l'expression de la fonction.

1. Amélioration de la déclaration des variables

C'est-à-dire que toutes les variables déclarées ou fonctions déclarées seront promues en haut de la fonction actuelle.

Par exemple, le code suivant :

console.log('x' in window);//true
var x;
x = 0;

Lorsque le code est exécuté, le moteur js élèvera l'instruction de déclaration en haut du code et deviendra :

var x;
console.log('x' in window);//true
x = 0;

2. Expression de fonction

var getName et function getName sont toutes deux des déclarations de déclaration. La différence est que var getName est une expression de fonction, tandis que la fonction getName est une déclaration de fonction. Pour plus d'informations sur la façon de créer diverses fonctions dans JS, vous pouvez lire les questions classiques de l'entretien de clôture JS que la plupart des gens posent mal. Cet article contient des explications détaillées.

Le plus gros problème avec les expressions de fonction est que js divisera ce code en deux lignes de code et les exécutera séparément.

Par exemple, le code suivant :

console.log(x);//输出:function x(){}
var x=1;
function x(){}

Le code réellement exécuté consiste d'abord à diviser var x=1 en deux lignes : var x; et x = 1;, puis à élever les deux lignes var x et function x(){} vers le haut pour devenir :

var x;
function x(){}
console.log(x);
x=1;

Ainsi, le x déclaré par la fonction finale couvre le x déclaré par la variable, et la sortie du journal est la fonction x.

De même, l'exécution finale du code dans la question d'origine est :

function Foo() {
 getName = function () { alert (1); };
 return this;
}
var getName;//只提升变量声明
function getName() { alert (5);}//提升函数声明,覆盖var的声明

Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明

getName();//最终输出4

Soalan ketiga

Dalam soalan ketiga, Foo().getName(); mula-mula melaksanakan fungsi Foo, dan kemudian memanggil fungsi atribut getName bagi objek nilai pulangan bagi fungsi Foo.

Ayat pertama fungsi Foo getName = function () { makluman (1 }); skop fungsi, dan tidak ada. Kemudian lihat ke lapisan atas skop fungsi semasa, iaitu, skop luar, untuk melihat sama ada ia mengandungi pembolehubah getName Ia ditemui, iaitu fungsi amaran(4) dalam soalan kedua pembolehubah kepada function(){alert(1) }.

Di sini, fungsi getName dalam skop luar sebenarnya diubah suai.

Nota: Jika ia masih tidak ditemui di sini, ia akan mencari sehingga ke objek tetingkap Jika tiada atribut getName dalam objek tetingkap, buat pembolehubah getName dalam objek tetingkap.

Selepas itu, nilai pulangan fungsi Foo adalah ini, dan sudah banyak artikel mengenai masalah JS ini di taman blog, jadi saya tidak akan menerangkan lebih lanjut di sini.

Ringkasnya, titik ini ditentukan oleh kaedah panggilan fungsi. Dalam kaedah panggilan langsung di sini, ini menunjuk ke objek tetingkap.

Fungsi Foo mengembalikan objek tetingkap, yang bersamaan dengan melaksanakan window.getName(), dan getName dalam tetingkap telah diubah suai kepada alert(1), jadi 1 akan dikeluarkan pada akhirnya

Dua perkara pengetahuan dikaji di sini, satu ialah isu skop pembolehubah dan satu lagi ialah isu penunjuk ini.

Soalan 4

Panggil terus fungsi getName, yang bersamaan dengan window.getName(), kerana pembolehubah ini telah diubah suai apabila fungsi Foo dilaksanakan, dan hasilnya adalah sama dengan soalan ketiga, iaitu 1

Soalan kelima

Soalan kelima ialah new Foo.getName( , apa yang dikaji di sini ialah isu keutamaan pengendali js.

Dengan melihat jadual di atas, kita boleh mengetahui bahawa keutamaan titik (.) adalah lebih tinggi daripada operasi baharu, yang bersamaan dengan:

baharu (Foo.getName)();
Jadi fungsi getName sebenarnya dilaksanakan sebagai pembina, dan 2 muncul.

Soalan 6

Soalan keenam ialah Foo().getName(). Pertama sekali, kurungan keutamaan operator adalah lebih tinggi daripada pelaksanaan sebenar ialah

(Foo baharu()).getName()
Kemudian fungsi Foo dilaksanakan terlebih dahulu, dan Foo, sebagai pembina, mempunyai nilai pulangan, jadi di sini kita perlu menerangkan nilai pulangan pembina dalam js.

Nilai pulangan pembina

Dalam bahasa tradisional, pembina tidak sepatutnya mempunyai nilai pulangan Nilai pulangan bagi pelaksanaan sebenar ialah objek instantiated bagi pembina ini.

Dalam js, pembina boleh mempunyai nilai pulangan atau tidak.

1. Jika tiada nilai pulangan, objek yang di instantiated akan dikembalikan seperti dalam bahasa lain.

2. Jika terdapat nilai pulangan, semak sama ada nilai pulangan adalah jenis rujukan. Jika ia adalah jenis bukan rujukan, seperti jenis asas (rentetan, nombor, boolean, null, undefined), ia adalah sama seperti tiada nilai pulangan dan objek instantiatednya sebenarnya dikembalikan.

3 Jika nilai pulangan ialah jenis rujukan, nilai pulangan sebenar ialah jenis rujukan ini.

Dalam soalan asal, ini dikembalikan, dan ini pada asalnya mewakili objek instantiated semasa dalam pembina, jadi fungsi Foo akhirnya mengembalikan objek instantiated.

Kemudian panggil fungsi getName bagi objek yang di instantiated Kerana tiada atribut ditambahkan pada objek yang di instantiated dalam pembina Foo, kami mencari getName dalam objek prototaip objek semasa dan mencarinya.

Keluaran akhir ialah 3.

Soalan 7

Soalan ketujuh, new new Foo().getName(); juga merupakan isu keutamaan pengendali.

Pelaksanaan sebenar terakhir ialah:

baharu ((Foo baharu()).getName)();
Mula-mula mulakan objek yang di-instantiate bagi Foo, dan kemudian gunakan fungsi getName pada prototaipnya sebagai pembina baharu semula.

Keputusan akhir ialah 3

Akhir sekali

Setakat jawapan, soalan pertama boleh dijawab dengan betul 100% masa, soalan kedua hanya kira-kira 50% betul, soalan ketiga boleh dijawab tidak banyak, dan soalan keempat sangat, sangat jarang. Sebenarnya, tidak banyak kegunaan yang rumit dan pelik untuk soalan ini. Semuanya adalah senario yang mungkin anda hadapi.

Saya hanya boleh mengatakan bahawa sesetengah orang terlalu tidak sabar dan tidak sabar. Saya harap semua orang dapat memahami beberapa ciri js melalui artikel ini.

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn