Maison > Article > interface Web > 23 questions d'entretien JavaScript que vous devez connaître
1. Utiliser typeof bar === "object" pour déterminer si la barre est un objet présente des inconvénients potentiels ? Comment éviter cet inconvénient ?
Les inconvénients de l'utilisation de typeof sont évidents (cet inconvénient est le même que celui de l'utilisation de instanceof) :
let obj = {}; let arr = []; console.log(typeof obj === 'object'); //true console.log(typeof arr === 'object'); //true console.log(typeof null === 'object'); //true
D'après les résultats de sortie ci-dessus, on peut voir que typeof bar = == "object" ne permet pas de déterminer avec précision que la barre est un objet. Vous pouvez éviter cet inconvénient en Object.prototype.toString.call(bar) === "[object Object]":
let obj = {}; let arr = []; console.log(Object.prototype.toString.call(obj)); //[object Object] console.log(Object.prototype.toString.call(arr)); //[object Array] console.log(Object.prototype.toString.call(null)); //[object Null]
De plus, afin de chérir la vie, veuillez rester à l'écart de == :
Et [] === false renvoie false.
Articles connexes recommandés : La collection la plus complète de questions d'entretien js en 2020 (dernière)
2. Le code suivant affichera-t-il un message sur la console ? Pourquoi?
(function(){ var a = b = 3; })(); console.log("a defined? " + (typeof a !== 'undefined')); console.log("b defined? " + (typeof b !== 'undefined'));
Ceci est lié à la portée de la variable. Le résultat est modifié comme suit :
console.log(b); //3 console,log(typeof a); //undefined
Démontez l'affectation de variable dans la fonction auto-exécutable :
b = 3; var a = b;
Donc b devient une variable globale et a est une variable locale de la fonction auto-exécutable.
3. Le code suivant affichera-t-il un message sur la console ? Pourquoi?
var myObject = { foo: "bar", func: function() { var self = this; console.log("outer func: this.foo = " + this.foo); console.log("outer func: self.foo = " + self.foo); (function() { console.log("inner func: this.foo = " + this.foo); console.log("inner func: self.foo = " + self.foo); }());
Il n'est pas difficile de juger les première et deuxième sorties. Avant ES6, JavaScript n'avait qu'une portée de fonction, donc l'IIFE dans func a sa propre portée indépendante, et il peut accéder à Self. dans la portée externe, donc la troisième sortie signalera une erreur car elle n'est pas définie dans la portée accessible, et la quatrième sortie est bar. Si vous connaissez les fermetures, c'est facile à résoudre :
function(test) { console.log("inner func: this.foo = " + test.foo); //'bar' console.log("inner func: self.foo = " + self.foo); }(self));
Si vous n'êtes pas familier avec les fermetures, vous pouvez vous référer à cet article : Parler des fermetures de la chaîne scope
4. Convertir du code JavaScript Que signifie l'inclure dans un bloc fonctionnel ? Pourquoi faire ça ?
En d’autres termes, pourquoi utiliser l’expression de fonction immédiatement invoquée ?
IIFE propose deux scénarios d'utilisation classiques, l'un est similaire à la sortie régulière d'éléments de données en boucle, et l'autre est similaire au développement de plug-ins et de modules JQuery/Node.
for(var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); }
La sortie ci-dessus n'est pas 0, 1, 2, 3, 4 comme vous le pensiez, mais toute la sortie est 5, alors IIFE peut être utile :
for(var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, 1000); })(i) }
Dans le développement de plug-ins et modules JQuery/Node, afin d'éviter la pollution variable, c'est aussi un gros IIFE :
(function($) { //代码 } )(jQuery);
5. Effectuer du JavaScript en mode strict (« use strict »). ) Quels sont les bénéfices du développement ?
Éliminez certains aspects déraisonnables et imprécis de la syntaxe Javascript et réduisez certains comportements étranges ;
Éliminez certains aspects dangereux de l'exécution du code et assurez la sécurité de l'exécution du code ;
Améliorez l'efficacité du compilateur et augmentez la vitesse d'exécution
ouvrez la voie à de nouvelles versions de Javascript à l'avenir.
6. Les valeurs de retour des deux fonctions suivantes sont-elles les mêmes ? Pourquoi?
La première consiste à augmenter d'abord la puissance, puis à la réduire :
function add(num1, num2){ let r1, r2, m; r1 = (''+num1).split('.')[1].length; r2 = (''+num2).split('.')[1].length; m = Math.pow(10,Math.max(r1,r2)); return (num1 * m + num2 * m) / m; } console.log(add(0.1,0.2)); //0.3 console.log(add(0.15,0.2256)); //0.3756
La seconde consiste à utiliser les méthodes intégrées toPrecision() et toFixed(). Notez que la chaîne de valeur de retour de la méthode .
function add(x, y) { return x.toPrecision() + y.toPrecision() } console.log(add(0.1,0.2)); //"0.10.2"
7. Implémentez la fonction isInteger(x) pour déterminer si x est un entier
Vous pouvez convertir x en décimal et déterminer s'il est égal à C'est tout :
function isInteger(x) { return parseInt(x, 10) === x; }
ES6 étend la valeur numérique et fournit la méthode statique isInteger() pour déterminer si le paramètre est un entier :
Number.isInteger(25) // true Number.isInteger(25.0) // true Number.isInteger(25.1) // false Number.isInteger("15") // false Number.isInteger(true) // false
La plage d'entiers qui JavaScript peut représenter avec précision entre -2^53 et 2^53 (à l'exclusion des deux points de terminaison), au-delà de cette plage, la valeur ne peut pas être représentée avec précision. ES6 a introduit deux constantes, Number.MAX_SAFE_INTEGER et Number.MIN_SAFE_INTEGER, pour représenter les limites supérieure et inférieure de cette plage, et a fourni Number.isSafeInteger() pour déterminer si un entier est un entier sûr.
8. Dans le code suivant, dans quel ordre les nombres 1 à 4 seront-ils affichés ? Pourquoi le résultat est-il ainsi ?
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })();
Je n'expliquerai pas grand-chose ici, il s'agit principalement du mécanisme de synchronisation et de la boucle temporelle de JavaScript. N'oubliez pas que JavaScript est monothread. Pour une explication détaillée, veuillez vous référer à Parler du mécanisme d'exécution de JavaScript de setTimeout.
9. Écrivez une fonction avec moins de 80 caractères pour déterminer si une chaîne est une chaîne palindrome
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join('')); }
J'ai rencontré cette question sur Codewars et j'en ai inclus Une bonne solution, vous pouvez cliquer ici : Palindrome pour votre dôme
10. Écrivez une méthode de somme qui peut fonctionner normalement lorsqu'elle est appelée de la manière suivante
console.log(sum(2,3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5
Destiné à Cette question peut être résolue. en jugeant le nombre de paramètres :
function sum() { var fir = arguments[0]; if(arguments.length === 2) { return arguments[0] + arguments[1] } else { return function(sec) { return fir + sec; } } }
11. Répondez aux questions suivantes en fonction de l'extrait de code ci-dessous
for (var i = 0; i < 5; i++) { var btn = document.createElement('button'); btn.appendChild(document.createTextNode('Button ' + i)); btn.addEventListener('click', function(){ console.log(i); }); document.body.appendChild(btn); }
1 Cliquez sur le bouton 4. Quoi. sera sorti sur la console ?
Cliquer sur l'un des 5 boutons affichera 5
2 Donnez une implémentation attendue
Référez-vous à IIFE.
12. Que produira le code suivant ? Pourquoi?
var arr1 = "john".split(''); j o h n var arr2 = arr1.reverse(); n h o j var arr3 = "jones".split(''); j o n e s arr2.push(arr3); console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1)); console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));
Quel sera le résultat ? Vous le saurez après l’avoir exécuté, et cela peut être inattendu.
reverse() modifiera le tableau lui-même et renverra une référence au tableau d'origine. Pour l'utilisation de
slice, veuillez vous référer à : slice
13. Que produira le code suivant ? Pourquoi?
console.log(1 + "2" + "2"); console.log(1 + +"2" + "2"); console.log(1 + -"1" + "2"); console.log(+"1" + "1" + "2"); console.log( "A" - "B" + "2"); console.log( "A" - "B" + 2);
输出什么,自己去运行吧,需要注意三个点:
多个数字和数字字符串混合运算时,跟操作数的位置有关
console.log(2 + 1 + '3'); / /‘33' console.log('3' + 2 + 1); //'321'
数字字符串之前存在数字中的正负号(+/-)时,会被转换成数字
console.log(typeof '3'); // string console.log(typeof +'3'); //number
同样,可以在数字前添加 '',将数字转为字符串
console.log(typeof 3); // number console.log(typeof (''+3)); //string
对于运算结果不能转换成数字的,将返回 NaN
console.log('a' * 'sd'); //NaN console.log('A' - 'B'); // NaN
14、什么是闭包?举例说明
可以参考此篇:从作用域链谈闭包
15、下面的代码会输出什么?为啥?
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000 ); }
请往前面翻,参考第4题,解决方式已经在上面了
16、解释下列代码的输出
console.log("0 || 1 = "+(0 || 1)); console.log("1 || 2 = "+(1 || 2)); console.log("0 && 1 = "+(0 && 1)); console.log("1 && 2 = "+(1 && 2));
逻辑与和逻辑或运算符会返回一个值,并且二者都是短路运算符:
逻辑与返回第一个是 false 的操作数 或者 最后一个是 true的操作数
console.log(1 && 2 && 0); //0 console.log(1 && 0 && 1); //0 console.log(1 && 2 && 3); //3
如果某个操作数为 false,则该操作数之后的操作数都不会被计算
逻辑或返回第一个是 true 的操作数 或者 最后一个是 false的操作数
console.log(1 || 2 || 0); //1 console.log(0 || 2 || 1); //2 console.log(0 || 0 || false); //false
如果某个操作数为 true,则该操作数之后的操作数都不会被计算
如果逻辑与和逻辑或作混合运算,则逻辑与的优先级高:
console.log(1 && 2 || 0); //2 console.log(0 || 2 && 1); //1 console.log(0 && 2 || 1); //1
在 JavaScript,常见的 false 值:
0, '0', +0, -0, false, '',null,undefined,null,NaN
要注意空数组([])和空对象({}):
console.log([] == false) //true console.log({} == false) //false console.log(Boolean([])) //true console.log(Boolean({})) //true
所以在 if 中,[] 和 {} 都表现为 true:
17、解释下面代码的输出
console.log(false == '0') console.log(false === '0')
18、解释下面代码的输出
var a={}, b={key:'b'}, c={key:'c'}; a[b]=123; a[c]=456; console.log(a[b]); 输出是456。
19、在下面的代码中,数字 1-4 会以什么顺序输出?为什么会这样输出?
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })();
这个就不多解释了,主要是 JavaScript 的定时机制和时间循环,不要忘了,JavaScript 是单线程的。详解可以参考 从setTimeout谈JavaScript运行机制。
20、写一个少于 80 字符的函数,判断一个字符串是不是回文字符串
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join('')); }
这个题我在 codewars 上碰到过,并收录了一些不错的解决方式,可以戳这里:Palindrome For Your Dome
21、写一个按照下面方式调用都能正常工作的 sum 方法
console.log(sum(2,3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5
针对这个题,可以判断参数个数来实现:
function sum() { var fir = arguments[0]; if(arguments.length === 2) { return arguments[0] + arguments[1] } else { return function(sec) { return fir + sec; } } }
22、解释下面代码的输出,并修复存在的问题
var hero = { _name: 'John Doe', getSecretIdentity: function (){ return this._name; } }; var stoleSecretIdentity = hero.getSecretIdentity; console.log(stoleSecretIdentity()); console.log(hero.getSecretIdentity());
将 getSecretIdentity 赋给 stoleSecretIdentity,等价于定义了 stoleSecretIdentity 函数:
var stoleSecretIdentity = function (){ return this._name; } stoleSecretIdentity
的上下文是全局环境,所以第一个输出 undefined。若要输出 John Doe,则要通过 call 、apply 和 bind 等方式改变 stoleSecretIdentity 的this 指向(hero)。
第二个是调用对象的方法,输出 John Doe。
23、给你一个 DOM 元素,创建一个能访问该元素所有子元素的函数,并且要将每个子元素传递给指定的回调函数。
函数接受两个参数:
DOM
指定的回调函数
原文利用 深度优先搜索(Depth-First-Search) 给了一个实现:
function Traverse(p_element,p_callback) { p_callback(p_element); var list = p_element.children; for (var i = 0; i < list.length; i++) { Traverse(list[i],p_callback); // recursive call } }
相关学习推荐:javascript视频教程