Maison >interface Web >js tutoriel >Introduction au principe de la nouvelle fonction d'appel en JS

Introduction au principe de la nouvelle fonction d'appel en JS

不言
不言original
2018-07-10 17:38:102380parcourir

Cet article présente principalement le principe de la nouvelle fonction d'appel en JS. Il a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer

Le constructeur est souvent utilisé en JavaScript pour créer. Objet (appel d'une fonction via l'opérateur new), que se passe-t-il exactement lorsque vous utilisez new pour appeler une fonction ? Examinons quelques exemples avant d’expliquer ce qui se passe dans les coulisses.

1) Regardez trois exemples

1.1 Aucune instruction de retour

Il n'y a pas d'instruction return à la fin du constructeur C'est également la situation par défaut lors de l'utilisation. le constructeur, et il renverra un Le nouvel objet est le suivant :

function Foo(age) {
  this.age = age;
}

var o = new Foo(111);
console.log(o);

Il s'agit d'un processus courant d'utilisation du constructeur pour créer un objet, et ce qui est imprimé est {age: 111}.

1.2 renvoie les données de type d'objet

dernier constructeur return données de type d'objet :

function Foo(age) {
  this.age = age;

  return { type: "我是显式返回的" };
}

var o = new Foo(222);
console.log(o);

imprime {type: '我是显式返回的'}, c'est-à-dire return Tous les précédents le travail est fait en vain, et finalement l'objet derrière return est restitué.

1.3 renvoie des données de type de base

Cela signifie-t-il que tant qu'il y a return à la fin du corps du constructeur, les données après return seront renvoyées ?

Jetons un coup d'œil à la situation du retour des données de type de base :

function Foo(age) {
  this.age = age;

  return 1;
}

var o = new Foo(333);
console.log(o);

Ce qui est imprimé est {age: 333}, ce qui a le même effet que sans return. C’est différent des attentes. Veuillez consulter l’analyse ci-dessous pour connaître le principe qui la sous-tend.

2) Le principe derrière

2.1 Le cas des fonctions non-flèches

Lors de l'utilisation de l'opérateur new pour créer des objets, la documentation officielle de l'ES5 est en Définition de la fonction La définition suivante est faite dans la section 13.2.2 [[Construct]] :

Lorsque la [[Construct]] méthode interne d'un Function objet F est appelée avec une liste éventuellement vide de arguments, les étapes suivantes sont suivies :

  1. Soit obj un objet ECMAScript natif nouvellement créé.

  2. Définir tout les méthodes internes d'obj comme spécifié dans 8.12.

  3. Définissez la propriété interne [[Class]] d'obj sur Object.

  4. Définissez les [[Extensible]] propriété interne de obj à true.

  5. Soit proto la valeur de l'appel de la propriété interne [[Get]] de F avec l'argument "prototype".

  6. Si Type(proto) est Object, définissez la propriété interne [[Prototype]] de obj sur proto.

  7. Si Type(proto) n'est pas Object, définissez la propriété interne [[Prototype]] de obj sur l'Object prototype object intégré standard comme décrit dans 15.2.4.

  8. Soit le résultat soit le résultat de l'appel de la propriété interne [[Call]] de F, fournissant obj comme valeur this et fournissant la liste d'arguments passée dans [[Construct] ] comme arguments.

  9. Si le type (résultat) est un objet, retournez le résultat.

  10. Retour obj.

Regardez les étapes 8 et 9 :

8) Appelez la fonction F et attribuez sa valeur de retour à result parmi eux, les paramètres réels lorsque est exécuté sont passés au paramètre F (c'est-à-dire [[Construct]] lui-même), F interne F pointe vers this9) Si obj est de type
, retournez ; resultObject resultCela explique également que si le constructeur renvoie explicitement le type d'objet, il renverra cet objet directement au lieu de renvoyer l'objet initialement créé.

Regardez enfin l'étape 10 :

10) Si

ne renvoie pas un type d'objet (l'étape 9 n'est pas vraie), renvoyez l'objet créé

.
FobjSi le constructeur ne renvoie pas explicitement le type d'objet (renvoie explicitement le type de données de base ou ne le renvoie pas directement), l'objet initialement créé est renvoyé.

2.2 Le cas de la fonction flèche

Et si le constructeur est une fonction flèche ?

Il n'y a pas de méthode

dans la fonction flèche. Elle ne peut pas être appelée en utilisant

et une erreur sera signalée.

[[Construct]]AVIS : où new fait référence au constructeur lui-même.

Les spécifications pertinentes sont mentionnées dans la documentation officielle d'ES6, mais la documentation officielle depuis ES6 est extrêmement difficile à comprendre et ne sera pas décrite ici. [[Construct]]

3) Le processus complet de nouvelle fonction d'appel
3.1 Description chinoise et analyse du code associée

Toute fonction à l'exception des fonctions fléchées peut être appelée en utilisant

Ce qui s'est passé derrière. la scène est très claire en anglais dans la section précédente, et elle est décrite en chinois comme suit :

1)创建 ECMAScript 原生对象 obj;  
2)给 obj 设置原生对象的内部属性;(和原型属性不同,内部属性表示为 [[PropertyName]],两个方括号包裹属性名,并且属性名大写,比如常见 [[Prototype]][[Constructor]])  
3)设置 obj 的内部属性 [[Class]]Object;  
4)设置 obj 的内部属性 [[Extensible]]true;  
5)将 proto 的值设置为 Fprototype 属性值;  
6)如果 proto 是对象类型,则设置 obj 的内部属性 [[Prototype]] 值为 proto;(进行原型链关联,实现继承的关键)  
7)如果 proto 是不对象类型,则设置 obj 的内部属性 [[Prototype]] 值为内建构造函数 Objectprototype 值;(函数 prototype 属性可以被改写,如果改成非对象类型,obj[[Prototype]] 就指向 Object 的原型对象)  
8)9)10)见上节分析。(决定返回什么)

对于第 7 步的情况,见下面代码:

function Foo(name) {
  this.name = name;
}

var o1 = new Foo("xiaoming");
console.log(o1.__proto__ === Foo.prototype); // true

// 重写构造函数原型属性为非对象类型,实例内部 [[Prototype]] 属性指向 Object 原型对象
// 因为实例是一个对象类型的数据,默认会继承内建对象的原型,
// 如果构造函数的原型不满足形成原型链的要求,那就跳过直接和内建对象原型关联
Foo.prototype = 1;
var o2 = new Foo("xiaohong");
console.log(o2.__proto__ === Foo.prototype); // false
console.log(o2.__proto__ === Object.prototype); // true

3.2 更简洁的语言描述

若执行 new Foo(),过程如下:

1)创建新对象 o;  
2)给新对象的内部属性赋值,关键是给[[Prototype]]属性赋值,构造原型链(如果构造函数的原型是 Object 类型,则指向构造函数的原型;不然指向 Object 对象的原型);  
3)执行函数 Foo,执行过程中内部 this 指向新创建的对象 o;  
4)如果 Foo 内部显式返回对象类型数据,则,返回该数据,执行结束;不然返回新创建的对象 o

4)几点说明

4.1 判断是否是 Object 类型

关于一个数据是否是 Object 类型,可以通过 instanceof 操作符进行判断:如果 x instanceof Object 返回 true,则 xObject 类型。

由上可知,null instanceof Object 返回 false,所以 null 不是 Object 类型,尽管typeof null 返回 "Object"。

4.2 instanceof 原理

instanceof 的工作原理是:在表达式 x instanceof Foo 中,如果 Foo 的原型(即 Foo.prototype)出现在 x 的原型链中,则返回 true,不然,返回 false

因为函数的原型可以被改写,所以会出现在 x 通过 Foo new 出来之后完全改写 Foo 的原型 x instanceof Foo 返回 false 的情况。因为实例创建之后重写构造函数原型,实例指向的原型已经不是构造函数的新的原型了,见下面代码:

const Foo = function() {};

const o = new Foo();

o instanceof Foo; // true

// 重写 Foo 原型
Foo.prototype = {};
o instanceof Foo; // false

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

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