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.
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}
.
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é.
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.
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 :
Soit obj un objet ECMAScript natif nouvellement créé.
Définir tout les méthodes internes d'obj comme spécifié dans 8.12.
Définissez la propriété interne [[Class]] d'obj sur Object.
Définissez les [[Extensible]] propriété interne de obj à true.
Soit proto la valeur de l'appel de la propriété interne [[Get]] de F avec l'argument "prototype".
Si Type(proto) est Object, définissez la propriété interne [[Prototype]] de obj sur proto.
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.
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.
Si le type (résultat) est un objet, retournez le résultat.
Retour obj.
Regardez les étapes 8 et 9 :
8) Appelez la fonctionF
et attribuez sa valeur de retour àresult
parmi eux, les paramètres réels lorsque est exécuté sont passés au paramètreF
(c'est-à-dire[[Construct]]
lui-même),F
interneF
pointe versthis
9) Siobj
est de type
, retournez ;result
Object
result
Cela 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) Sine renvoie pas un type d'objet (l'étape 9 n'est pas vraie), renvoyez l'objet créé
.F
obj
Si 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éthodedans 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]]
1)创建 ECMAScript 原生对象 obj
;
2)给 obj
设置原生对象的内部属性;(和原型属性不同,内部属性表示为 [[PropertyName]]
,两个方括号包裹属性名,并且属性名大写,比如常见 [[Prototype]]
、[[Constructor]]
)
3)设置 obj
的内部属性 [[Class]]
为 Object
;
4)设置 obj
的内部属性 [[Extensible]]
为 true
;
5)将 proto
的值设置为 F
的 prototype
属性值;
6)如果 proto
是对象类型,则设置 obj
的内部属性 [[Prototype]]
值为 proto
;(进行原型链关联,实现继承的关键)
7)如果 proto
是不对象类型,则设置 obj
的内部属性 [[Prototype]]
值为内建构造函数 Object 的 prototype
值;(函数 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
若执行 new Foo()
,过程如下:
1)创建新对象 o
;
2)给新对象的内部属性赋值,关键是给[[Prototype]]
属性赋值,构造原型链(如果构造函数的原型是 Object 类型,则指向构造函数的原型;不然指向 Object 对象的原型);
3)执行函数 Foo
,执行过程中内部 this
指向新创建的对象 o
;
4)如果 Foo
内部显式返回对象类型数据,则,返回该数据,执行结束;不然返回新创建的对象 o
。
关于一个数据是否是 Object
类型,可以通过 instanceof
操作符进行判断:如果 x instanceof Object
返回 true
,则 x
为 Object
类型。
由上可知,null instanceof Object
返回 false
,所以 null
不是 Object
类型,尽管typeof null
返回 "Object"。
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!