Questions d'entretien javascript haute fréquence frontales - mises à jour en permanence

Table des matières

1. La différence entre == et ===, dans quelles situations sont-ils utilisés ?

2. Méthodes pour déterminer le type de données

3. Parlez des types de données en JavaScript ? Différence de stockage ?

4. Opérateurs en JavaScript

5.var,let,const

 6. La différence entre la copie profonde et la copie superficielle et comment la mettre en œuvre

7. Anti-tremblement et limitation

8.La différence entre setTimeout() et setInterval()

9.Objet mathématique

10.Quelle est la différence entre les cookies, sessionStorage et localStorage ?

 11. La différence entre obtenir et poster

12.http et https 

13.Étapes de base d'ajax et les cinq états de readyState et les principes d'ajax

 14. Quels sont les moyens de retarder le chargement de JS ?

15. Quelle est la différence entre null et indéfini ?

16.js macro-tâche et micro-tâche

17. Méthodes de fonctionnement du tableau

18. Méthodes de chaîne 

19. Pourquoi 0,1+0,2 ! == 0,3, comment le rendre égal 

20.Comment obtenir une valeur sûre et indéfinie ?

21. Quel est le résultat du type de NaN ?

 22. Quelle est la différence entre Object.is() et les opérateurs de comparaison "===" et "==" ?

23.Les propriétés des objets const peuvent-elles être modifiées ?

24. Que se passera-t-il si new est une fonction fléchée ?

25. La différence entre les fonctions fléchées et les fonctions ordinaires

26. Principe de mise en œuvre du nouvel opérateur

 27. Pourquoi les arguments de la fonction sont-ils un pseudo-tableau au lieu d'un tableau ? Comment parcourir un pseudo tableau ?

28. Comprendre AJAX et implémenter une requête AJAX

29.Quelle est la différence entre les méthodes forEach et map ? 

30. Compréhension de la promesse

31. Parlez de la différence entre les attributs différés et asynchrones dans les balises de script.

32. Parlez-moi de votre compréhension de la clôture.

33. Veuillez expliquer le mécanisme de bouillonnement des événements

34. Méthodes pour empêcher les événements de bouillonner 

 35.Qu'est-ce que la délégation d'événements ? Quels sont ses avantages ?

36. Supprimer aléatoirement une valeur du tableau

37.Javascript interdit au navigateur de revenir à la page précédente

38.Le terminal mobile Jquery interdit le zoom du navigateur 

39. Comment parcourir toutes les propriétés d'un objet et afficher leurs valeurs sur la console ?

40. Comment obtenir le type de données d'une variable via une fonction ?

41. Générer des chaînes aléatoires

42. Générer des nombres aléatoires dans la plage spécifiée

43. Il existe de nombreuses façons de formater de l'argent, comme ces deux manières.

44. Mise à jour continue ~~~


1. La différence entre == et ===, dans quelles situations sont-ils utilisés ?

égal à l'opérateur

L'opérateur égal est représenté par deux signes égal (==). Si les opérandes sont égaux, il renverra true

Nous savons JavaScriptqu'il existe des conversions implicites dans . L'opérateur égal (==) effectuera d'abord la conversion de type lors de la comparaison, puis déterminera si les opérandes sont égaux.

1. let result = (true == 1); // true    
如果任一操作数是布尔值,则将其转换为数值再比较是否相等

2. let result = ("55" == 55); // true    
如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等

3. let obj = {valueof:Function(){return 1}}
   let result = (obj == 1); // true
如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法取得其原始值,再根据前面的规则进行比较

    
4. let result = (null == undefined ); // true
null 和undefined相等

5. let result = (NaN == NaN ); // false
null 和undefined相等


6. let obj1 = {name:"xxx"}
let obj2 = {name:"xxx"}
let result = (obj1 == obj2 ); // false
如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true

Résumé de l'opérateur égal :

  • Les deux sont des types simples. Les chaînes et les valeurs booléennes seront converties en valeurs numériques puis comparées.

  • Comparez les types simples avec les types référence, convertissez l'objet en une valeur de son type d'origine, puis comparez

  • Si les deux sont des types référence, comparez s’ils pointent vers le même objet.

  • null et indéfini sont égaux

  • Si NaN existe, renvoie false

opérateur congruent 

L'opérateur d'identité est représenté par trois signes égaux (===) et renvoie uniquement si les deux opérandes sont égaux sans conversion  true. Autrement dit, si les types sont les mêmes, les valeurs doivent également être les mêmes.

1. let result1 = ("55" === 55); // false,不相等,因为数据类型不同
   let result2 = (55 === 55); // true,相等,因为数据类型相同值也相同
   
   undefined 和 null 与自身严格相等
2. let result1 = (null === null)  //true
   let result2 = (undefined === undefined)  //true

 Résumé des opérateurs congrus :

  • L'opérateur d'égalité n'effectue pas de conversion de type

  • null et  undefined comparaison, conforme àfalse

La différence entre l'opérateur de congruence et l'opérateur égal

        L'opérateur d'égalité (==) effectuera une conversion de type puis comparera les valeurs, tandis que l'opérateur de congruence n'effectuera pas de conversion de type. 

2. Méthodes pour déterminer le type de données

1.typeOf 2.instanceof 3.object.prototype.toString.call 4.constructeur 

//1.typeOf
let obj={
   name:'dawn',
   age:21
}
let fn=function() {
    console.log('我是 function 类型');
}
console.log(typeof 1);       //number
console.log(typeof 'abc');   //string
console.log(typeof true);    //boolean
console.log(typeof undefined);  //undefined 
console.log(typeof fn);      //function
console.log(typeof (new Date) );  //object
console.log(typeof null);     //object
console.log(typeof [1,2,3]);  //object
console.log(typeof obj);      //object
//由结果可知typeof可以测试出number、string、boolean、undefined及function。对于null及数组、对象,typeof均检测出为object,不能进一步判断它们的类型。



//2.instanceof
let arr=[1,2,3,4,5,6,7]
let obj={
   name:'dawn',
   age:21
}
let fn=function() {
   console.log('我是 function 类型');
}
console.log(arr instanceof Array);  //true
console.log(obj instanceof Object);  //true
console.log(fn instanceof Function);  //true
console.log((new Date) instanceof Date);  //true
//obj instanceof Object ,可以左边放你要判断的内容,右边放类型来进行JS类型判断,只能用来判断复杂数据类型,因为instanceof 是用于检测构造函数(右边)的 prototype 属性是否出现在某个实例对象(左边)的原型链上。




//3.Object.prototype.toString.call
let obj = {
   name: 'dawn',
   age: 21
}
let fn = function () {
   console.log('我是 function 类型');
}    
console.log(Object.prototype.toString.call(1));        // [object Number]   
console.log(Object.prototype.toString.call('Hello tomorrow')); // [object String ]
console.log(Object.prototype.toString.call(true));     // [object Boolean]
console.log(Object.prototype.toString.call(undefined));  // [object Undefined]
console.log(Object.prototype.toString.call(fn));   // [object Function]
console.log(Object.prototype.toString.call(new Date));  // [object Date]
console.log(Object.prototype.toString.call(null));   // [object Null]
console.log(Object.prototype.toString.call([1, 2, 3]));  // [object Array]
console.log(Object.prototype.toString.call(obj));       // [object Object]
//在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。
但是它不能检测非原生构造函数的构造函数名。



//4.constructor
let arr = [1, 2, 3, 4, 5, 6, 7]
let obj = {
   name: 'dawn',
   age: 21
}
let fn = function () {
   console.log('我是 function 类型');
} 
console.log((9).constructor === Number);  //true
console.log('hello'.constructor === String);  //true
console.log(true.constructor === Boolean);  //true
console.log(fn.constructor === Function);  //true
console.log((new Date).constructor === Date);  //true
console.log(obj.constructor === Object);  //true
console.log([1, 2, 3].constructor === Array);  //true
//constructor不能判断undefined和null,并且使用它是不安全的,因为contructor的指向是可以改变的

3. Parlez des types de données en JavaScript ? Différence de stockage ?

Les types de données en JavaScript sont divisés en :

        Types de données de base : nombre, chaîne, booléen, non défini, nul, symbole

        Types de données complexes : Objet, Tableau, Fonction, Date, RegExp,...etc

Différence de stockage :

        Les types de données de base sont stockés sur la pile

        Les objets de type référence sont stockés dans le tas

//1.基本类型
let a = 10;
let b = a; // 赋值操作
b = 20;
console.log(a); // 10值
//a的值为一个基本类型,是存储在栈中,将a的值赋给b,虽然两个变量的值相等,但是两个变量保存了两个不同的内存地址


//2.引用类型
var obj1 = {}
var obj2 = obj1;
obj2.name = "Xxx";
console.log(obj1.name); // xxx
//引用类型数据存放在内对内中,每个堆内存中有一个引用地址,该引用地址存放在栈中obj1是一个引用类型,在赋值操作过程汇总,实际是将堆内存对象在栈内存的引用地址复制了一份给了obj2,实际上他们共同指向了同一个堆内存对象,所以更改obj2会对obj1产生影响

 Résumer:

  • Différentes allocations d'adresses mémoire lors de la déclaration de variables :
    • Les valeurs de types simples sont stockées sur la pile et les valeurs correspondantes sont stockées sur la pile
    • La valeur correspondant au type de référence est stockée dans le tas, et l'adresse pointant vers la mémoire tas est stockée dans la pile
  • Différents types de données entraînent des différences lors de l'attribution des variables :
    • L'affectation de type simple consiste à générer la même valeur et deux objets correspondent à des adresses différentes
    • L'affectation de type complexe consiste à attribuer l'adresse mémoire de l'objet enregistré à une autre variable. Autrement dit, les deux variables pointent vers le même objet dans la mémoire tas.

4. Opérateurs en JavaScript

//1.递增递减操作符
//使用++、--两种符号表示递增和递减,同时根据符号位置的不同,又分为前置递增递减和后置递增递减:
var num1 = 10;
var n = ++num1; // 前置递增,先执行递增计算,再对n进行赋值,所以,n=11,num1=11
var num2 = 10;
var m = --num2; // 前置递减,先执行递减计算,再对m进行赋值,所以,m=9,num2=9
var x = num2++; // 后置递增,先赋值,再执行递增计算,所以,x=9,num2=10;


//2.一元加、一元减操作符
//+表示一元加操作符,-表示一元减操作符,这两种操作符放在数值前面,相当于属数学中的正负号。
var a = 10;
console.log(-a); // -10
console.log(+a); // 10


//3.布尔操作符
//布尔操作符有三个:与、或、非
//&& 逻辑与    两边都是true,才返回true,否则返回false
//|| 逻辑或    两边只要有一个是true,就返回true,否则返回false
//! 逻辑非   用来取一个布尔值相反的值  
{} && false; // false
false && {}; // {}
{na:1} && {na:2}; // {na:2}
null && false; // null
NaN && false; // NaN
undefined && false; // undefined

{} || false; // {}
1 === 2 || false; // false
{n:1} || {n:2}; // {n:1}
null || null; // null
NaN || NaN; // NaN
undefined || undefined; // undefined 

//在进行||、&&操作时,如果有一个操作数不是布尔值,返回结果也不一定是布尔值:

5.var,let,const

  1. Les variables définies par var peuvent être pré-analysées et le résultat d'un appel anticipé n'est pas défini. Les variables définies par let ne peuvent pas être pré-analysées. Le résultat d'un appel anticipé est une erreur ( ReferenceError ) . Les variables définies par const ne peuvent pas être pré-analysées et le résultat d'un appel préalable est une erreur.
  2. Pour les variables définies par var, le nom de la variable peut être répété et l'effet est une affectation répétée. Les variables définies par let ne peuvent pas être répétées, sinon une erreur sera signalée lors de l'exécution. Les variables définies par const ne peuvent pas être répétées, sinon une erreur sera signalée lors de l'exécution.
  3. La portée de la variable définie par var est la portée globale/locale. Les variables définies par let ne peuvent être appelées dans {} que si elles sont dans {}.
  4. Variables de boucle définies par var dans l'instruction de boucle et variables de boucle définies à l'aide de let. Les principes d'exécution et les effets d'exécution sont différents.
  5. La valeur des données stockée dans la variable définie par const ne peut pas être modifiée, c'est-à-dire que la variable définie par const ne peut pas être attribuée à plusieurs reprises.
//提前使用
console.log(a)    //提前调用 预解析
console.log(b)   //报错
var a = 1
let b = 2

//const与let 定义的变量不能重复
var init = 11
var init = 22
let init2 = 11
let init2 = 22
console.log(init)   //22  var声明的变量被重新赋值
consoloe.log(init2) //会报错

//const与let 定义的变量如果在{}中那么只能在{}中来使用
if (true) {
  var a = 300;
  let b = 400;
  const c = 500;
  // let 声明的变量 在 { } 中可以调用
  console.log(b);
  console.log(c);
}
console.log(a);   //300
// let和const 声明的变量 在 { } 外 不能调用 
console.log(c);  //报错
console.log(b);  //报错


//const定义的变量 不能重复赋值
const aa = 100
aa = 200
console.log(aa)  //报错

const a = {
    name: 'zhang',
    age: '18'
}
console.log(a.name)//zhang
a.name = 'zhen';
console.log(a.name)//zhen

const b = [1, 2, 3, 4, 5]
console.log(b[0])//1
b[0] = 0;
console.log(b[0])//0
//const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

questions d'examen

        Quelle est l’entrée du code suivant ?

                

        fonction direSalut() {

                console.log(nom);

                console.log(âge);

                nom de la variable = "Xiong Da" ;

                soit âge = 18 ;

        }

A : Xiong Dahe  undefined  B : Xiong Dahe  ReferenceError  C :  ReferenceError Et 18   D :  undefined Et ReferenceError

La réponse est : D. Comment le comprenez-vous réellement ?

 6. La différence entre la copie profonde et la copie superficielle et comment la mettre en œuvre

copie superficielle:

        Attribuez directement la référence de l'objet d'origine ou du tableau d'origine au nouvel objet, au nouveau tableau et au nouvel objet. Le nouvel objet est simplement une référence à l'objet d'origine sans copier l'objet lui-même. Les anciens et les nouveaux objets partagent toujours la même mémoire. .

        Si l'attribut est un type de données de base, la valeur copiée est le type de base. Si l'attribut est un type de référence, l'adresse mémoire est copiée.

Copie profonde :

        Créez un nouvel objet et un nouvel tableau, et copiez les "valeurs" de chaque attribut de l'objet d'origine (tous les éléments du tableau). Ce sont des "valeurs" plutôt que des "références".

        La copie profonde consiste à copier complètement un objet de la mémoire, à ouvrir une nouvelle zone de la mémoire tas pour stocker le nouvel objet et à modifier le nouvel objet sans affecter l'objet d'origine.

Méthode de copie superficielle :

        affectation directe d'objet

        Objet.assign

La méthode de copie profonde :

        JSON.stringify en chaîne et JSON.parse en objet

        Traversée récursive profonde

        Écrivez une solution récursive (recommandée et relativement parfaite) pour encapsuler une fonction de copie complète de DeepClone

//浅拷贝
//1.直接对象赋值
let a = [0,1,2,3,4];
b = a;
console.log(a === b);
a[0] = 1;
console.log(a, b) // a=11234  b=11234

//2. 解构赋值
var obj1 = {a: 1, b: 2}
var obj2 = {...obj1}
obj2.a = 4
console.log(obj1, obj2) //obj1 = {a:1,b:2}   obj2 = {a:4,b:2}

//3.Object.assign()
let obj1 = { 
	a: { b: 1}, 
	c: 2
}
let obj2 = Object.assign({},obj1)
obj2.a.b = 3;  //第二层,obj1变了,是浅拷贝
obj2.c = 3;  //第一层,obj1不变,是深拷贝
console.log(obj1);  //{a:{b:3},c:2}
console.log(obj2);  //{a:{b:3},c:3}
//严格来说,Object.assign() 既不是深拷贝,也不是浅拷贝——而是第一级属性深拷贝,第一级以下的级别属性浅拷贝。

//深拷贝
//1.封装deepClone深拷贝的方法
function DeepClone(data) {
  const newData = Array.isArray(data) ? [] : {}
  for (let key in data) {
    if (data[key] && typeof data[key] === 'object') {
       newData[key] = DeepClone(data[key])
    } else {
      newData[key] = data[key]
    }
  }
  return newData
}
//调用他
const obj2 = DeepClone(obj1)

//2.JSON.stringify转为字符串再JSON.parse
//JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
//缺点:当值为undefined、function、symbol 会在转换过程中被忽略

//3.jquery 提供一个 $.extend 可以用来做深拷贝;
var obj = {a:{name:"kaiqin",age:19}};
var obj1 = {b:{name:"wang",age:19}};
var obj2 = $.extend(true,{},obj,obj1); //true为深拷贝,false为浅拷贝,默认为false
obj2.a.name="zhang";
console.log(obj2)
//{a: {name: "zhang", age: 19},b: {name: "wang", age: 19}}
console.log(obj)
//{
   
   {a:{name:"kaiqin",age:19}}}

7. Anti-tremblement et limitation

Anti-shake : Anti-shake signifie que la fonction ne peut être exécutée qu'une seule fois dans les n secondes suivant le déclenchement de l'événement. Si l'événement est à nouveau déclenché dans les n secondes, le temps d'exécution de la fonction sera recalculé. DOM Peut être utilisé pour la somme de contrôle d'entrée en temps réel input.change et l'événement window.resize, par exemple, une fois le zoom de la fenêtre terminé, la taille partielle sera recalculée 

Limitation : ce que l'on appelle la limitation signifie que les événements sont déclenchés en continu mais que la fonction n'est exécutée qu'une fois toutes les n secondes. Il existe deux manières d'y parvenir, à savoir la version timestamp et la version timer . Utilisé pour la surveillance  mousemove, le défilement de la souris et d'autres événements, généralement utilisé pour : l'animation par glisser-déposer, le chargement par liste déroulante.

//防抖
//用定时器实现防抖
function debounce(fn, wait) {
    let timout = null;
    return function () {
        clearTimeout(timout)
        timout = setTimeout(fn, wait)
    }
}


//节流
//定时器实现节流
function throttle(func, wait) {
    var timer = null;
    return function () {
        var _this = this;
        var args = arguments;
        if (!timer) {
            timer = setTimeout(function () {
                timer = null;
                func.apply(_this, args)
            }, wait)
        }
    }
}

//时间戳实现节流
function throttle(func, wait) {
    //定义初始时间
    var oldTime = 0;
    return function () {
        var _this = this;
        var args = arguments;
        //当前时间戳
        var newTime = +new Date();
        //判断用当前时间减去旧的时间,如果大于wait指定的时间就会触发
        if (newTime - oldTime > wait) {
            //执行触发的函数
            func.apply(_this, args)
            //将旧时间更新
            oldTime = newTime;
        }

    }

8.La différence entre setTimeout() et setInterval()

1. Dans les mêmes conditions, setTimeout() n'est exécuté qu'une seule fois , et setInterval() est exécuté en boucle ;
2. setTimeout() est exécuté une fois avec un délai : setTimeout(fn, 1000); //Délai 1 seconde et exécuter fn() une fois ;
3. exécution cyclique de setInterval() à intervalles réguliers ; setInterval(fn, 1000); //toutes les 1 secondes, exécution cyclique de fn()

9.Objet mathématique

Math.PI                // 圆周率
Math.random()          // 生成随机数
Math.floor()           // 向下取整
Math.ceil()            //向上取整
Math.round()           // 取整,四舍五入
Math.abs()             // 绝对值
Math.max()             //求最大值
Math.min()             //求最小值
Math.sin()             // 正弦
Math.cos()             //余弦
Math.power()           // 求指数次幂
Math.sqrt()            //求平方根


//求10到20的随机数
//生成 min 到 max 之间的随机数
var min = 10;
var max = 20;
console.log( parseInt(Math.random() * (max - min) + min));

10.Quelle est la différence entre les cookies, sessionStorage et localStorage ?

Même point :

        SessionStorage, LocalStorage et Cookie peuvent tous être utilisés pour stocker des données côté navigateur, et ce sont toutes des paires clé-valeur de type chaîne.

différence:

        SessionStorage : la taille des données de stockage est d'environ 5 Mo. Elles ne participent pas à la communication du serveur et seront effacées à la fermeture de la page ou du navigateur actuel.

        localStorage : la taille des données de stockage est d'environ 5 Mo ou plus, ne participe pas à la communication du serveur et est valide en permanence à moins qu'elle ne soit supprimée manuellement ou que le code ne soit supprimé.

        Cookies : petites données textuelles d'une taille d'environ 4 Ko, généralement générées par le serveur. Le délai d'expiration peut être défini. S'il n'y a aucun paramètre, fermez le navigateur et il expirera.

 11. La différence entre obtenir et poster

  1. get est généralement utilisé pour obtenir des demandes, et post est généralement utilisé pour soumettre des demandes.
  2. Get a tendance à être placé dans l'URL et la publication a tendance à être placée dans le corps.
  3. Fondamentalement, les deux méthodes de requête ne sont pas suffisamment sécurisées, car http lui-même est un protocole en texte clair, la pratique courante en matière de sécurité consiste donc à utiliser le protocole de cryptage par clé https. Et comme get est placé dans le corps de la requête, il est relativement sûr d'utiliser post+body
  4. La limite de longueur de l'obtention des données fait en fait référence à la limite de longueur de l'URL, mais le protocole http lui-même n'impose aucune limite sur la longueur de l'URL. La limite réelle est limitée par le client/navigateur et le serveur.

12.http et https 

  1. Le protocole https nécessite de demander un certificat auprès de CA. Généralement, il y a moins de certificats gratuits, donc certains frais sont requis.
  2. http est un protocole de transfert hypertexte et les informations sont transmises en texte brut, tandis que https est un protocole de transmission sécurisé et crypté SSL.
  3. http et https utilisent des méthodes de connexion complètement différentes et utilisent des ports différents. Le premier est 80 et le second est 443.
  4. La connexion http est très simple et sans état ; le protocole HTTPS est un protocole réseau construit à partir du protocole SSL+HTTP qui peut effectuer une transmission cryptée et une authentification d'identité, et est plus sécurisé que le protocole http.

13.Étapes de base d'ajax et les cinq états de readyState et les principes d'ajax

//1创建对象xmlhttprequest
const xhr = new XMLHTTPRequest();
//2创建一个http请求初始化
xhr.open('GET','/api',false);
//3send发送请求
xhr.send();
//4监听状态变化
xhr.onreadystatechange = function(){
 //5查看状态码判断状态
 if(xhr.readyState == 4){
   if(xhr.status >= 200 &&xhr.status <= 300){
   }
 }
}

Cinq états de readyState :

  1. Non initialisé 0
  2. Chargement 1
  3. Chargement terminé 2
  4. Commencer l'analyse 3
  5. Analyse terminée 4

Le principe d'ajax :

        Le principe d'ajax est que le navigateur demande à xhr (XmlHttpRequest) de demander des données au serveur, et le navigateur fait autre chose. Lorsque le serveur renvoie les données à xhr, xhr en informe le navigateur et le navigateur restitue les données à la page. .

 14. Quels sont les moyens de retarder le chargement de JS ?

<script defer type="text/javascript" src='script.js'></script>
//defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。

15. Quelle est la différence entre null et indéfini ?

null est un objet représentant « aucun » (pointeur d'objet nul), qui vaut 0 lorsqu'il est converti en valeur numérique ;

undefined est une valeur primitive représentant « aucun », qui est NaN lorsqu'elle est convertie en valeur numérique.

16.js macro-tâche et micro-tâche

Les tâches de macro js incluent : les événements setTimeout, setInterval, Ajax, DOM

Les microtâches js incluent : process.nextTick, Promise.then catch

 Qui exécute en premier les macro-tâches ou les micro-tâches js ?

        JS est monothread. S'il rencontre une exécution synchrone, il sera exécuté de manière synchrone jusqu'à ce que l'exécution soit terminée. S'il rencontre une exécution asynchrone, il sera placé dans la file d'attente d'exécution. Asynchronie (macro-tâches et micro-tâches), les micro-tâches sont mieux que les tâches macro en exécution asynchrone.

setTimeout(() => {
  console.log(4);
})
new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})
console.log(2)

         setTimeout est asynchrone, il est donc ignoré et arrive à la synchronisation dans l'exécution de Promise, console.log(1) . Vient ensuite un processus asynchrone, ignoré. Le dernier est un code de synchronisation console.log(2). L'étape suivante est le code asynchrone que nous avons ignoré auparavant. De haut en bas, le premier est setTimeout et l'autre est Promise.then().

        setTimeout est l'asynchronisme des tâches macro et Promise.then() est l'asynchronisme des microtâches. Les microtâches sont exécutées avant les macrotâches, donc à ce moment, la tâche setTimeout sera ignorée en premier et deux microtâches de Promise.then() seront exécuté. . La fonction console.log(3) sera donc exécutée à ce moment-là. Au final, il ne reste plus qu'à exécuter la fonction setTimeout, donc console.log(4) est finalement exécuté.

        Pour résumer l’analyse ci-dessus : résultats d’exécution 1 2 3 4        

17. Méthodes de fonctionnement du tableau

//数组的操作方法
    push() //1.从数组末尾追加
    unshift() //2.从数组前面添加
    pop() //3.从数组末尾删除
    shift() //4.从数组头部删除
    reverse() //5.数组反转
    sort() //6.数组排序
    splice() //7.删除 添加 替换
    //以上七种可以修改数组本身
    forEach() //8.循环遍历
    concat() //9.拼接数组
    filter() //10.过滤数组
    slice() //11.截取元素
    every() //12.判断数组中是否有满足
    some() //13.只要有一个满足条件返回值就是true,没有满足条件的则为false
    reduce() //14.数组求和
    indexO() //15.查找值  从前往后查找
    lastIndexOf() //16.查找值  是从后往前查找。
    toString() //17.把数组转换为字符串
    join() //18.把数组转换为字符串, 可以传入不同的符号进行连接 默认用逗号连接
    toLocaleString() //19.把数组转换为字符串
    map() //20.指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。返回新数组
    find() //21.返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
    flat() //22.按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。此方法不会改变原数组。depth 可选 指定要提取嵌套数组的结构深度,默认值为 1。如果不确定嵌套多少层,可以使用ES10新增:BigInt 表示任意大的整数
    findIndex() //23.方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
    Array.at()  //24.返回指定索引处的值。
    
//数组的操作方法
//1.push()从数组末尾追加
//push从数组末尾添加,返回值是数组的长度,会改变原数组
var arr = [1, 2, 3, 4, 5]
console.log(arr.push(6, 7));        // 7 arr数组的长度 
console.log(arr);                   //输出结果:[1, 2, 3, 4, 5, 6, 7]

//2.unshift()从数组前面添加
//unshift从数组前面添加,返回值是数组的长度,会改变原数组
var arr = [1, 2, 3, 4, 5]
console.log(arr.unshift(6, 7));        // 7 arr数组的长度 
console.log(arr);                      //输出结果:[ 6, 7, 1, 2, 3, 4, 5 ]

//3.pop()从数组末尾删除
//pop 从数组末尾删除,返回值是删除的值,会改变原数组
var arr = [1, 2, 3, 4, 5]
console.log(arr.pop());        // 5 删除的值
console.log(arr);              //输出结果:[ 1, 2, 3, 4 ]

//4.shift()从数组头部删除
//shift 从数组头部删除,返回值是删除的值,会改变原数组
var arr = [1, 2, 3, 4, 5]
console.log(arr.shift());        // 1 删除的值
console.log(arr);                //输出结果:[ 2, 3, 4,5 ]

//5.reverse()数组反转
//reverse数组反转,返回值是反转后的数组,会改变原数组
var arr = [1, 2, 3, 4, 5]
console.log(arr.reverse());        // [5, 4, 3, 2, 1]
console.log(arr);                  //输出结果:[5, 4, 3, 2, 1]

//6.sort()数组排序
//sort数组排序,返回值是排序后的数组,会改变原数组
var arr = [1, 2, 3, 4, 5, 9, 8, 7, 6]
console.log(arr.sort());           //[1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(arr);                  //输出结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]

//7.splice()删除 添加 替换
//splice(index,howmany,arr1,arr2),删除元素并添加元素,从index位置开始删除howmany个元素,
//并将arr1,arr2数据从index位置依次插入。howmany为0时,则不删除元素。
//splice数组排序,返回值是删除的数组,会改变原数组
var arr = [1, 2, 3, 4, 5]
console.log(arr.splice(0,2,111,222));           //[1, 2]
console.log(arr);                  //输出结果: [111, 222, 3, 4, 5]

//以上七种方法是修改原数组的

//8.forEach()循环遍历
//forEach循环遍历,没有返回值,回调函数的参数,第一个参数是数组的每一项,第二个参数是数组中每一项的下标,第三个参数是数组的本身。
var arr = [1, 2, 3, 4, 5]
arr.forEach((item,index,abc) => {console.log(item,index,abc)})

//9.concat()拼接数组
//用来拼接数组 并且 会返回一个新数组。
var arr = [1, 2, 3, 4, 5, 6];
console.log(arr.concat([7, 8, 9]));    //输出结果:[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
var arr1 = [1, 2, 3, 4, 5, 6];
var arr2 = [7, 8, 9]
var arr3 = arr1.concat(arr2)
console.log(arr1);      //[ 1, 2, 3, 4, 5, 6 ]
console.log(arr3);      //输出结果:[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

//10.filter()过滤数组
//filter返回值是一个新的数组,filter里面可以直接 return 筛选条件 
let arr = [20, 50, 80, 90]
let newArr = arr.filter((item, index, array) => {    
//item:数组每一项,index:数组每一项的x下标,array:数组本身
    return item >= 70
})
console.log(newArr);  //返回筛选后的数组 [ 80, 90 ]

//11.slice()截取元素
//slice( ):数组元素的截取,返回一个新数组,新数组是截取的元素,可以为负值。
//从数组中截取,如果不传参,会返回原数组。如果只传入一个参数,会从头部开始删除,直到数组结束,原数组不会改变;传入两个参数,第一个是开始截取的索引,第二个是结束截取的索引,不包含结束截取的这一项,原数组不会改变。最多可以接受两个参数。
let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
console.log(arr.slice(0, 2));     // 返回值是被删除的元素['a','b']  
console.log(arr);                 //['a', 'b', 'c', 'd', 'e', 'f', 'g']

//12.every()判断数组中是否有满足
//every遍历数组  一般用于判断数组中是否有满足条件的数组元素,所有元素遍历之后,所有元素都满足条件的元素是返回值为true,若有一个不满足则返回false.
var arr = [1, 2, 3, 4, 5, 6]
console.log(arr.every(item => item > 1));     //输出结果:false
var arr = [1, 2, 3, 4, 5, 6]
console.log(arr.every(item => item > 0));     //输出结果:true

//13.some()只要有一个满足条件返回值就是true,没有满足条件的则为false
//some方法和every方法非常的类似 ,所有元素遍历之后,所有元素都满足条件的元素是返回值为true,若有一个不满足则返回false.
var arr = [1, 2, 3, 4, 5, 6]
console.log(arr.every(item => item > 6));     //输出结果:false
var arr = [1, 2, 3, 4, 5, 6]
console.log(arr.every(item => item > 3));     //输出结果:true

//14.reduce()数组求和
//1.reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
​//2.reduce方法可以接收两个参数,第一个参数:要执行的函数,第二个参数:函数迭代的初始值
//3.第一个参数不是函数吗?函数里面的参数如下
    prev:上次调用函数的返回值
    cur:当前元素
    index:当前元素索引
    arr:被遍历的数组
//4.array.reduce(function(prev, currentValue, currentIndex, arr), initValue) //initValue是第二个参数
//不传入函数迭代的初始值
const arr = [11, 22, 33, 44]
const sum = arr.reduce((prev, cur, index) => {
   console.log(prev, cur, index);
   return prev + cur
})        //没有传入函数迭代的初始值, 初始值默认是数组第一位 , prev 就是计算结束后的返回值。
console.log('sum:', sum);   //110   
//传入函数迭代的初始值
const arr = [11, 22, 33, 44]
const sum = arr.reduce((prev, cur, index) => {
   console.log(prev, cur, index);
   return prev + cur
}, 10)    //传入函数迭代的初始值之后,也就是让 prev 从10开始累加,然后接着迭代累加 prev 
console.log('sum:', sum);    //120

//15.indexO()查找值  从前往后查找
//接受两个参数:查找的值、查找起始位置
//不存在,返回 -1 ;存在,返回位置。
var arr = [1, 2, 3, 4, 5]
console.log(arr.indexof(2,3))  //-1

//16.lastIndexOf()查找值  是从后往前查找。
//接受两个参数:查找的值、查找起始位置
//不存在,返回 -1 ;存在,返回位置。
var arr = [1, 2, 3, 4, 5]
console.log(arr.lastIndexOf(2,3))  //1

//17.toString()把数组转换为字符串
var arr = [1, 2, 3, 4, 5]
console.log(arr.toString())    //'1,2,3,4,5'

//18.join()把数组转换为字符串, 可以传入不同的符号进行连接 默认用逗号连接
var arr = [1, 2, 3, 4, 5]
console.log(arr.join('|'))    //'1|2|3|4|5'

//19.toLocaleString()把数组转换为字符串
var arr = [1, 2, 3, 4, 5]
console.log(arr.toLocaleString())    //'1,2,3,4,5'

//20.map()指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。返回新数组
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.map(function(item){
return item*item;
});
console.log(arr2); //[1, 4, 9, 16, 25]

//21.find()
//返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
// 获取数组中第一个大于10的值
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found);// expected output: 12

//22.flat()
//按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。此方法不会改变原数组。
//depth 可选 指定要提取嵌套数组的结构深度,默认值为 1。如果不确定嵌套多少层,可以使用ES10新增:BigInt 表示任意大的整数
const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat());// log: [0, 1, 2, 3, 4]
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2));// log: [0, 1, 2, [3, 4]]

//23.findIndex()方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
//IE 11 及更早版本不支持 findIndex() 方法
var arr2 = [1,18,2,99,666,44,66];
var flag2 = arr2.findIndex(item => {
   return item > 50;
});    //当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,如果没有符合条件的元素返回 -1
console.log(flag2)   // 得到: 3

//24.Array.at()返回指定索引处的值。
const list = [1, 2, 3, 4, 5];
list.at(1); // 2
list.at(-1); // 5
list.at(-2); // 4

18. Méthodes de chaîne 

//字符串常用方法
    charAt()        //1.返回在指定位置的字符
    charCodeAt()    //2.返回在指定的位置的字符的 Unicode 编码。
    concat()        //3.连接字符串。
    indexOf()       //4.检索字符串。indexOf() 方法对大小写敏感。
    match()         //5.是用来查找字符的 
    includes()      //6.判断字符串是否包含指定的子字符串。
    repeat()        //7.字符串复制指定次数
    replace()       //8.方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
    replaceAll()    //9.字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,该函数会替换所有匹配到的子字符串。
    search()        //10.方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。返回与指定查找的字符串或者正则表达式相匹配的 String 对象起始位置。
    slice()         //11.提取字符串的某个部分,并以新的字符串返回被提取的部分。
    split()         //12.方法用于把一个字符串分割成字符串数组
    substring()     //13.方法用于提取字符串中介于两个指定下标之间的字符。
    toLowerCase()   //14.方法用于把字符串转换为小写。
    toUpperCase()   //15.方法用于把字符串转换为大写。
    trim()          //16.删除字符串的头尾空白符,空白符包括:空格、制表符 tab、换行符等其他空白符等
    includes(), startsWith(), endsWith()    //17.来确定一个字符串是否包含在另一个字符串中
    
//1.charAt()返回在指定位置的字符
var str="abc"
console.log(str.charAt(0))//a

//2.charCodeAt()返回在指定的位置的字符的 Unicode 编码。
var str="abc"
console.log(str.charCodeAt(1))//98

//3.concat()连接字符串。
var a = "abc";  
var b = "def";  
var c = a.concat(b);
console.log(c);//abcdef

//4.indexOf()检索字符串。indexOf() 方法对大小写敏感。
var str="Hello world!"
console.log(str.indexOf("Hello"))//0
console.log(str.indexOf("World"))//-1
console.log(str.indexOf("world"))///6

//5.match()是用来查找字符的 
//方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置
var str = 'asdfghajkwyai';
var result = str.match('a');   //result = a
//如果想查找所有满足的匹配结果,就要加一个 g 才会返回所有满足匹配的结果
var str = 'asdfghajkwyai';
var result = str.match(/a/g);    //result = aaa
//若没有标志 g,.match()方法就只执行一次匹配,找到结果就返回,不会接着去查找;若没有找到任何匹配文本,.match()方法将会返回nul;
//若有标志 g,.match()就会返回一个数组,数组中存放所有满足查找条件的信息;

//6.includes()判断字符串是否包含指定的子字符串。
let str = "Hello";
let s = str.includes("e");
console.log(s); //true
//语法:string.includes(searchvalue, start)
//searchvalue 必需值,要查找的字符串。
//start 可选值,设置从那个位置开始查找,默认为 0。

//7.repeat()字符串复制指定次数
let str = "Hello";
let s = str.repeat(2);
console.log(s); //HelloHello
//语法:string.repeat(count)
//count 必需,设置要复制的次数。

//8.replace()字符替换
let str = "Hello";
let s = str.replace("l", "o");
console.log(s); //Heolo
//语法:string.replace(searchvalue,newvalue)
//searchvalue 必须。规定子字符串或要替换的模式的 RegExp 对象。
//请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为RegExp对象。
//newvalue 必需。一个字符串值。规定了替换文本或生成替换文本的函数。

//9.replaceAll()字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,该函数会替换所有匹配到的子字符串。
let str = "Hello";
let s = str.replaceAll("l", "o");
console.log(s); //Heooo
//语法同replace方法相同

//10.search()
//search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。返回与指定查找的字符串或者正则表达式相匹配的 String 对象起始位置。
let str = "Hello";
let s = str.search("lo");
console.log(s); //3
//语法:string.search(searchvalue)
//searchvalue 必须。查找的字符串或者正则表达式。

//11.slice()提取字符串的某个部分,并以新的字符串返回被提取的部分。
let str = "Hello";
let s = str.slice(1, 2);
console.log(s); //e
//语法:string.slice(start,end)
//start 必须。 要抽取的片断的起始下标,第一个字符位置为 0。如果为负数,则从尾部开始截取。
//end 可选。 紧接着要截取的片段结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。

//12.split() 方法用于把一个字符串分割成字符串数组
let str = "Hello";
let s = str.split("e");
console.log(str); //Hello
console.log(s); //[ 'H', 'llo' ]
//语法:string.split(separator,limit)
//separator 可选。字符串或正则表达式,从该参数指定的地方分割 string Object。
//limit 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。

//13.substring() 方法用于提取字符串中介于两个指定下标之间的字符。
let str = "Hello";
let s = str.substring(1, 3);
console.log(str); //Hello
console.log(s); //el
//语法:string.substring(from, to)
//from 必需。一个非负的整数,规定要提取的子串的第一个字符在 string Object 中的位置。
//to 可选。一个非负的整数,比要提取的子串的最后一个字符在 string Object 中的位置多 1。
如果省略该参数,那么返回的子串会一直到字符串的结尾。

//14,15.toLowerCase()和toUpperCase()方法
let str = "Hello";
let s = str.toLowerCase();
let s2 = str.toUpperCase();
console.log(str); //Hello
console.log(s); //hello
console.log(s2);//HELLO

//16.trim()删除字符串的头尾空白符,空白符包括:空格、制表符 tab、换行符等其他空白符等
let str = "    Hello   ";
let s = str.trim();
console.log(str); //    Hello
console.log(s); //Hello

//17.includes(), startsWith(), endsWith()来确定一个字符串是否包含在另一个字符串中
let s = 'Hello world!';
console.log(s.startsWith('world', 6));// true
console.log(s.endsWith('Hello', 5));// true
console.log(s.includes('Hello', 6));// false
//注意:第二个参数,表示开始搜索的位置。

Déduplication de chaînes

var str="aahhgggsssjjj";
function removeRepeat(n){
var k=[];
var arr=n.split("");
for(var i=0;i<arr.length;i++){
    if(k.indexOf(arr[i])==-1){
        k.push(arr[i]);
    }
}
return k.join("");
}
removeRepeat(str);    //ahgsj

19. Pourquoi 0,1+0,2 ! == 0,3, comment le rendre égal 

Au cours du processus de développement, j'ai rencontré des problèmes similaires à celui-ci :

let n1 = 0.1, n2 = 0.2
console.log(n1 + n2)  // 0.30000000000000004

Ce que vous obtenez ici n'est pas le résultat souhaité. Si vous voulez qu'il soit égal à 0,3, vous devez le convertir :

(n1 + n2).toFixed(2) // 注意,toFixed为四舍五入

toFixed(num) Méthode pour arrondir le nombre à un nombre avec le nombre spécifié de décimales.

20.Comment obtenir une valeur sûre et indéfinie ?

Parce qu'undéfini est un identifiant, il peut être utilisé et attribué comme variable, mais cela affectera le jugement normal d'undéfini. L'expression void ___ n'a pas de valeur de retour, le résultat renvoyé n'est donc pas défini. void ne change pas le résultat de l'expression, il fait simplement en sorte que l'expression ne renvoie aucune valeur. Vous pouvez donc utiliser void 0 pour ne pas être défini.

21. Quel est le résultat du type de NaN ?

NaN signifie "pas un nombre". NaN est une "valeur d'avertissement" utilisée pour indiquer des conditions d'erreur dans les types numériques, c'est-à-dire "l'exécution d'une opération mathématique n'a pas réussi, et voici le résultat renvoyé après un échec". 

typeof NaN; // "number"

NaN est une valeur spéciale qui n’est pas égale à elle-même. Et NaN !== NaN est vrai.

 22. Quelle est la différence entre Object.is() et les opérateurs de comparaison "===" et "==" ?

  • Lors de l'utilisation du double signe égal (==) pour le jugement d'égalité, si les types des deux côtés sont incohérents, une conversion de type forcée sera effectuée avant la comparaison.
  • Lors de l'utilisation du triple signe égal (===) pour le jugement d'égalité, si les types des deux côtés sont incohérents, la conversion de type forcée ne sera pas effectuée et false sera renvoyé directement.
  • Lorsque vous utilisez Object.is pour le jugement d'égalité, il s'agit généralement du triple signe égal. Il gère certaines situations particulières, telles que -0 et +0 ne sont plus égaux et deux NaN sont égaux.

23.Les propriétés des objets const peuvent-elles être modifiées ?

Ce que const garantit, ce n'est pas que la valeur de la variable ne peut pas être modifiée, mais que l'adresse mémoire pointée par la variable ne peut pas être modifiée. Pour les types de données de base (valeurs numériques, chaînes, valeurs booléennes), la valeur est stockée à l'adresse mémoire pointée par la variable, elle équivaut donc à une constante.

Pour les données de type référence, la variable pointe vers l'adresse mémoire des données et n'enregistre qu'un pointeur. Const ne peut garantir que ce pointeur est fixe. Quant à savoir si la structure de données vers laquelle elle pointe est variable, elle est complètement incontrôlable. 

24. Que se passera-t-il si new est une fonction fléchée ?

La fonction flèche a été proposée dans ES6. Elle n'a pas de prototype, ni son propre pointeur this. Elle ne peut pas utiliser de paramètres d'arguments, elle ne peut donc pas créer de fonction flèche.

Les étapes de mise en œuvre du nouvel opérateur sont les suivantes : 

  1. créer un objet
  2. Attribuez la portée du constructeur au nouvel objet (c'est-à-dire pointez l'attribut __proto__ de l'objet vers l'attribut prototype du constructeur)
  3. Pointe vers le code dans le constructeur, et celui-ci dans le constructeur pointe vers l'objet (c'est-à-dire l'ajout de propriétés et de méthodes à cet objet)
  4. Renvoyer un nouvel objet

Dans les deuxième et troisième étapes ci-dessus, les fonctions fléchées ne peuvent pas être exécutées.

25. La différence entre les fonctions fléchées et les fonctions ordinaires

  1.  Les fonctions fléchées sont plus concises que les fonctions ordinaires (s'il n'y a pas de paramètres, écrivez simplement directement un crochet vide, s'il n'y a qu'un seul paramètre, vous pouvez omettre les crochets de paramètre)

  2. Les fonctions fléchées n'ont pas leur propre ceci

  3. Le point hérité de la fonction flèche ne changera jamais.

  4. Les méthodes telles que call(), apply() et bind() ne peuvent pas changer la direction de ceci dans la fonction flèche.

  5. Les fonctions fléchées ne peuvent pas être utilisées comme constructeurs

  6. Les fonctions fléchées n'ont pas leurs propres arguments

  7. La fonction flèche n'a pas de prototype

  8. Les fonctions fléchées ne peuvent pas être utilisées comme fonctions génératrices et le mot-clé yeild ne peut pas être utilisé.

26. Principe de mise en œuvre du nouvel opérateur

Le processus d'exécution du nouvel opérateur :

(1) Créez d’abord un nouvel objet vide

(2) Définissez le prototype et définissez le prototype de l'objet sur l'objet prototype de la fonction.

(3) Laissez le this de la fonction pointer vers cet objet, exécutez le code du constructeur (ajoutez des propriétés à ce nouvel objet)

(4) Déterminez le type de valeur de retour de la fonction, s'il s'agit d'un type valeur, renvoyez l'objet créé. S'il s'agit d'un type référence, un objet de ce type référence est renvoyé.

Méthode pour réaliser

function objectFactory() {
  let newObject = null;
  let constructor = Array.prototype.shift.call(arguments);
  let result = null;
  if (typeof constructor !== "function") {// 判断参数是否是一个函数
    console.error("type error");
    return;
  }
  // 新建一个空对象,对象的原型为构造函数的 prototype 对象
  newObject = Object.create(constructor.prototype);
  // 将 this 指向新建对象,并执行函数
  result = constructor.apply(newObject, arguments);
  // 判断返回对象
  let flag = result && (typeof result === "object" || typeof result === "function");
  // 判断返回结果
  return flag ? result : newObject;
}
// 使用方法
objectFactory(构造函数, 初始化参数);

 27. Pourquoi les arguments de la fonction sont-ils un pseudo-tableau au lieu d'un tableau ? Comment parcourir un pseudo tableau ?

argumentsest un objet, ses attributs sont des nombres qui commencent à 0 et augmentent en séquence, ainsi que calleeet et lengthd'autres attributs, qui sont similaires aux tableaux ; mais il n'a pas les attributs de méthode communs aux tableaux, tels que forEachreduceetc., donc ils sont appelés pseudo-tableaux.

Trois méthodes de traversée dans des tableaux

La première

function foo(){ 
  Array.prototype.forEach.call(arguments, a => console.log(a))
}
//将数组的方法应用到类数组上,这时候就可以使用call和apply方法。

Le deuxième type

function foo(){ 
  const arrArgs = Array.from(arguments) 
  arrArgs.forEach(a => console.log(a))
}
//使用Array.from方法将类数组转化成数组

Le troisième genre

function foo(){ 
    const arrArgs = [...arguments] 
    arrArgs.forEach(a => console.log(a)) 
}
//使用展开运算符将类数组转化成数组

28. Comprendre AJAX et implémenter une requête AJAX

AJAX est l'abréviation de Asynchronous JavaScript et XML, qui fait référence à une communication asynchrone via JavaScript, obtenant un document XML du serveur, en extrayant des données, puis mettant à jour la partie correspondante de la page Web actuelle sans actualiser la page Web entière.

Étapes pour créer une requête AJAX :

  1. Créez un objet XMLHttpRequest.
  2. Utilisez la méthode open sur cet objet pour créer une requête HTTP . Les paramètres requis par la méthode open sont la méthode de requête, l'adresse de la requête, si elle est asynchrone et les informations d'authentification de l'utilisateur.
  3. Avant de faire une requête, vous pouvez ajouter quelques informations et fonctions d'écoute à cet objet . Par exemple, vous pouvez ajouter des informations d'en-tête à la demande via la méthode setRequestHeader. Vous pouvez également ajouter une fonction d'écoute de statut à cet objet. Un objet XMLHttpRequest a un total de 5 états. Lorsque son état change, l'événement onreadystatechange sera déclenché. Vous pouvez définir une fonction d'écoute pour gérer le résultat d'une requête réussie. Lorsque l'état prêt de l'objet passe à 4, cela signifie que les données renvoyées par le serveur ont été reçues. A ce moment, l'état de la demande peut être jugé. Si l'état est 2xx ou 304, cela signifie que le retour est normale. À ce stade, la page peut être mise à jour grâce aux données de la réponse.
  4. Une fois les propriétés et les fonctions d'écoute de l'objet définies, la méthode d'envoi est finalement appelée pour lancer une requête au serveur . Les paramètres peuvent être transmis en tant que corps de données à envoyer.
const SERVER_URL = "/server";
let xhr = new XMLHttpRequest();
// 创建 Http 请求
xhr.open("GET", url, true);
// 设置状态监听函数
xhr.onreadystatechange = function() {
  if (this.readyState !== 4) return;
  // 当请求成功时
  if (this.status === 200) {
    handle(this.response);
  } else {
    console.error(this.statusText);
  }
};
// 设置请求失败时的监听函数
xhr.onerror = function() {
  console.error(this.statusText);
};
// 设置请求头信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
// 发送 Http 请求
xhr.send(null);

 Utilisez Promise pour envelopper AJAX :

// promise 封装实现:
function getJSON(url) {
  // 创建一个 promise 对象
  let promise = new Promise(function(resolve, reject) {
    let xhr = new XMLHttpRequest();
    // 新建一个 http 请求
    xhr.open("GET", url, true);
    // 设置状态的监听函数
    xhr.onreadystatechange = function() {
      if (this.readyState !== 4) return;
      // 当请求成功或失败时,改变 promise 的状态
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    // 设置错误监听函数
    xhr.onerror = function() {
      reject(new Error(this.statusText));
    };
    // 设置响应的数据类型
    xhr.responseType = "json";
    // 设置请求头信息
    xhr.setRequestHeader("Accept", "application/json");
    // 发送 http 请求
    xhr.send(null);
  });
  return promise;
}

29.Quelle est la différence entre les méthodes forEach et map ? 

sont utilisés pour parcourir le tableau

  • La méthode forEach() exécutera la fonction fournie pour chaque élément, et l'opération sur les données modifiera le tableau d'origine, et cette méthode n'a aucune valeur de retour ;
  • La méthode map() ne changera pas la valeur du tableau d'origine, mais renvoie un nouveau tableau, et la valeur dans le nouveau tableau est la valeur après avoir appelé la fonction du tableau d'origine ;

30. Compréhension de la promesse

Promise est une solution pour la programmation asynchrone. C'est un objet qui peut obtenir des messages d'opérations asynchrones. Son apparence améliore considérablement le dilemme de la programmation asynchrone et évite l'enfer des rappels. Il est plus raisonnable que les fonctions et événements de rappel des solutions traditionnelles. et plus puissant.

En termes simples, Promise est un conteneur qui stocke le résultat d'un événement (généralement une opération asynchrone) qui se terminera dans le futur. Syntaxiquement, une promesse est un objet à partir duquel les messages d'une opération asynchrone peuvent être obtenus. Promise fournit une API unifiée et diverses opérations asynchrones peuvent être traitées de la même manière.

Les instances de promesse ont trois états :

  • En attente
  • Résolu
  • Rejeté

Une instance de Promise a deux processus

  • en attente -> réalisé : Résolu (terminé)
  • en attente -> rejeté : Rejeté

Remarque : Une fois que le statut passe du statut en cours à un autre statut, le statut ne peut plus être modifié.

31. Parlez de la différence entre les attributs différés et asynchrones dans les balises de script.

La différence est la suivante.

(1) L'attribut defer spécifie s'il faut retarder l'exécution du script jusqu'à ce que la page soit chargée, et l'attribut async spécifie si le script sera exécuté de manière asynchrone une fois disponible.

(2) différer charge les fichiers JavaScript en parallèle et sera exécuté dans l'ordre des balises de script sur la page. Async charge les fichiers JavaScript en parallèle et sera exécuté immédiatement après la fin du téléchargement. Il ne sera pas exécuté dans l'ordre de les balises de script sur la page.

32. Parlez-moi de votre compréhension de la clôture.

L'objectif principal de l'utilisation des fermetures est de concevoir des méthodes et des variables privées. L'avantage de la fermeture est qu'elle peut éviter la pollution des variables globales ; l'inconvénient est que la fermeture résidera en mémoire, augmentera l'utilisation de la mémoire et une mauvaise utilisation peut facilement provoquer des fuites de mémoire. En JavaScript, les fonctions sont des fermetures, et seules les fonctions peuvent générer des fermetures de portée qui ont 3 caractéristiques

(1) Fonction fonction imbriquée.

(2) Les paramètres et variables externes peuvent être référencés à l'intérieur de la fonction

(3) Les paramètres et variables ne seront pas recyclés par le mécanisme de collecte des ordures

33. Veuillez expliquer le mécanisme de bouillonnement des événements

Le bouillonnement d'événements signifie que lorsqu'un événement démarre, il est reçu par l'élément le plus spécifique (le nœud le plus bas du document), puis se propage vers le nœud le moins spécifique (le document). Par exemple, il y a un élément div sur une page, plus un événement click. Lorsque l'événement click est déclenché, son processus de livraison est div→body→html→document (en laissant de côté l'ancienne version pour l'instant), et il se déplacera le DOM L'arborescence est passée niveau par niveau.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			.outer{
				width: 200px;
				height: 200px;
				background: red;
				z-index: 1;
			}
			.cent{
				width: 100px;
				height: 100px;
				background: blue;
				position: absolute;
				right: 0;
				left: 0;
				bottom: 0;
				top: 0;
				margin:auto;
				z-index: 2;
			}
			.insert{
				width: 50px;
				height: 50px;
				background: orange;
				position: absolute;
				right: 0;
				left: 0;
				bottom: 0;
				top: 0;
				margin:auto;
				z-index: 3;
			}
			div{
				position: relative;
			}
		</style>
	</head>
	<body>
		<div class="outer">
			<div class="cent">
				<div class="insert"></div>
			</div>
		</div>
	</body>
	<script type="text/javascript">
		var Outer=document.getElementsByClassName("outer")[0];
		var Cent=document.getElementsByClassName("cent")[0];
		var Insert=document.getElementsByClassName("insert")[0];
		var aBody=document.getElementsByTagName("body")[0];
		Outer.onclick=function(){
			console.log("aaa")
		}
		Cent.onclick=function(){
			console.log("bbb")
		}
		Insert.onclick=function(){
			console.log("ccc")
		}
		aBody.onclick=function(){
			console.log("我是body")
		}

	</script>
</html>


    Lorsque vous cliquez sur l'élément Insérer, ccc, bbb, aaa et I am body seront affichés en séquence. C'est le mécanisme de bouillonnement d'événements.

34. Méthode pour empêcher les événements de bouillonner 

Il existe deux manières d'empêcher la diffusion d'événements :

  1. storpPapagation() // Ne prend pas en charge les versions inférieures d'IE
  2. CancelBubble=true

formulation compatible

 if(event.storpPrapagation){

           event.storpPrapation();

}autre{

           CancelBubble=true;

}

 35.Qu'est -ce que la délégation d'événements ? A quoi ça sert ?

La délégation d'événements fait référence à l'utilisation du principe de bouillonnement pour ajouter des événements au parent.Les avantages du déclenchement des effets d'exécution sont les suivants.

  • Réduisez le nombre d’événements et améliorez les performances.

  • En prédisant les éléments futurs, les éléments nouvellement ajoutés peuvent toujours déclencher l'événement.

  • Évitez les fuites de mémoire. Dans les versions inférieures de Positive E, évitez les débordements de mémoire provoqués par la suppression d'éléments sans supprimer les événements.

36. Supprimer aléatoirement une valeur du tableau

var arr = ['1', '2', '3'];
var index = Math.floor((Math.random() * arr.length));
console.log(arr[index]);

37.Javascript interdit au navigateur de revenir à la page précédente

<script type="text/javascript">
  $(function () {
    if (window.history && window.history.pushState) {
      $(window).on('popstate', function () {
        window.history.pushState('forward', null, '#');
        window.history.forward(1);
      });
    }
    window.history.pushState('forward', null, '#'); //在IE中必须得有这两行
    window.history.forward(1);
  })
</script>

38.Le terminal mobile Jquery interdit le zoom du navigateur 

Pour désactiver le zoom sur les navigateurs mobiles, vous pouvez ajouter un attribut à la balise viewportlors de l'initialisation de la page . De cette manière, lorsque l'utilisateur tente de zoomer sur la page dans le navigateur mobile, le navigateur ne répondra pas à l'opération de zoom de l'utilisateur.metauser-scalable=no

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

39. Comment parcourir toutes les propriétés d'un objet et afficher leurs valeurs sur la console ?

for (let key in obj) {
  console.log(key + ": " + obj[key]);
}

40. Comment obtenir le type de données d'une variable via une fonction ?

  const getType = (value) => {
    const match = Object.prototype.toString.call(value).match(/ (\w+)]/)
    return match[1].toLocaleLowerCase()
  }
  console.log(getType());// undefined
  console.log(getType({}));// object
  console.log(getType([]));// array
  console.log(getType(1));// number
  console.log(getType('fatfish'));// string
  console.log(getType(true));// boolean
  console.log(getType(/fatfish/));// regexp

41. Générer des chaînes aléatoires


const randomString = (len) => {
  let chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz123456789";
  let strLen = chars.length;
  let randomStr = "";
  for (let i = 0; i < len; i++) {
    randomStr += chars.charAt(Math.floor(Math.random() * strLen));
  }
  return randomStr;
};

randomString(10) // pfkMfjEJ6x
randomString(20) // ce6tEx1km4idRNMtym2S

42. Générer des nombres aléatoires dans la plage spécifiée


const randomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

randomNum(1, 10) // 6
randomNum(10, 20) // 11

43. Il existe de nombreuses façons de formater de l'argent, comme ces deux manières.

La première façon de formater de l'argent

const formatMoney = (money) => {
  return money.replace(new RegExp(`(?!^)(?=(\\d{3})+${money.includes('.') ? '\\.' : '$'})`, 'g'), ',')  
}

formatMoney('123456789') // '123,456,789'
formatMoney('123456789.123') // '123,456,789.123'
formatMoney('123') // '123'

Deuxième façon de formater de l'argent

 Les expressions régulières nous donnent vraiment mal à la tête, n'est-ce pas ? Nous devons donc trouver un moyen plus simple de formater la devise.

const formatMoney = (money) => {
  return money.toLocaleString()
}

formatMoney(123456789) // '123,456,789'
formatMoney(123456789.123) // '123,456,789.123'
formatMoney(123) // '123'

44. Mise à jour continue ~~~

おすすめ

転載: blog.csdn.net/m0_63873004/article/details/126709330