博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript constructors, prototypes, and the `new` keyword
阅读量:6716 次
发布时间:2019-06-25

本文共 6939 字,大约阅读时间需要 23 分钟。

Are you baffled(阻碍;使迷惑) by the new operator in JavaScript? Wonder what the difference between a function and a constructor is? Or what the heck a prototype is used for?

I’m going to lay it out straight.

Now, there’s been a lot of talk for a long time about so-called “pseudo-classical” JavaScript. Mostly, the new guard of JavaScript folk don’t like to use the new keyword. It was written into the language to act more like Java, and its use is a little confusing. I’m not going to take sides here. I’m just going to explain how it works. It’s a tool; use it if it’s practical.

WHAT IS A CONSTRUCTOR?

A constructor is any function which is used as a constructor. The language doesn’t make a distinction. A function can be written to be used as a constructor or to be called as a normal function, or to be used either way.

A constructor is used with the new keyword:

var Vehicle = function Vehicle() {  // ...}var vehicle = new Vehicle();

WHAT HAPPENS WHEN A CONSTRUCTOR IS CALLED?

When new Vehicle() is called, JavaScript does four things:

  1. It creates a new object.
  2. It sets the constructor property of the object to Vehicle.
  3. It sets up the object to delegate to Vehicle.prototype.
  4. It calls Vehicle() in the context of the new object.

The result of new Vehicle() is this new object.

1. IT CREATES THE NEW OBJECT.

This is nothing special, just a fresh, new object: {}.

2. IT SETS THE CONSTRUCTOR PROPERTY OF THE OBJECT TO VEHICLE.

This means two things:

vehicle.constructor == Vehicle  // truevehicle instanceof Vehicle      // true

This isn’t an ordinary property. It won’t show up if you enumerate the properties of the object. Also, you can try to set constructor, but you’ll just set a normal property on top of this special one. To wit:

vehicle;                          // {}var FuzzyBear = function FuzzyBear() { };vehicle.constructor = FuzzyBear;vehicle;                          // { constructor: function FuzzyBear() }vehicle.constructor == FuzzyBear; // truevehicle instanceof FuzzyBear      // falsevehicle instanceof Vehicle        // true

The underlying, built in constructor property is something you can’t set manually. It can only be set for you, as part of construction with the new keyword.

为了避免很多新手忘记使用new关键字,所以会提供工厂方法,但是这个时候就必须担心类型比较的问题:

 

3. IT SETS UP THE OBJECT TO DELEGATE TO VEHICLE.PROTOTYPE.

Now it gets interesting.

A function is just a special kind of object, and like any object a function can have properties. Functions automatically get a property called prototype, which is just an empty object. This object gets some special treatment.

When an object is constructed, it inherits all of the properties of its constructor’s prototype. I know, it’s a brainful. Here.

Vehicle.prototype.wheelCount = 4;var vehicle = new Vehicle;vehicle.wheelCount;         // 4

The Vehicle instance picked up the wheelCount from Vehicle‘s prototype

Now this “inheritance” is more than simply copying properties to the new objects. The object is set up to delegate any properties which haven’t been explicitly set up to its constructor’s prototype. That means that we can change the prototype later, and still see the changes in the instance.

Vehicle.prototype.wheelCount = 6;vehicle.wheelCount;         // 6

But if we like, we can always override it.

vehicle.wheelCount = 8;vehicle.wheelCount          // 8(new Vehicle()).wheelCount  // 6;

We can do the same thing with methods. After all, a method is just a function assigned to a property. Check it.

Vehicle.prototype.go = function go() { return "Vroom!" };vehicle.go();                              // "Vroom!"

4. IT CALLS VEHICLE() IN THE CONTEXT OF THE NEW OBJECT.

Finally, the constructor function itself is called. Inside the function, this is set to the object we’re constructing. (Why? Because that’s what Java does.) So,

var Vehicle = function Vehicle(color) {  this.constructor;       // function Vehicle()  this.color = color;}(new Vehicle("tan")).color;   // "tan"

Side note: Above, I said the use of the new keyword returned the constructed object. This is correct unless the constructor returns something explicitly. Then that object is returned, and the constructed object is just dropped. But really. JavaScript slaves over a hot CPU to create this object for you and then you just throw it away? Rude. And confusing to people who use your constructor. So unless you have a really good reason, don’t return anything from constructor functions.

PUTTING IT ALL TOGETHER

Given this tool, here’s one way (the intended way, but not the only way) to implement something like classes in JavaScript.

// Class definition / constructorvar Vehicle = function Vehicle(color) {  // Initialization  this.color = color;}// Instance methodsVehicle.prototype = {  go: function go() {    return "Vroom!";  }}

“SUBCLASSING”

This “pseudoclassical” style doesn’t have an exact way to make subclasses, but it comes close. We can set the prototype of our “subclass” to an instance of the “superclass”.

var Car = function Car() {};Car.prototype = new Vehicle("tan");Car.prototype.honk = function honk() { return "BEEP!" };var car = new Car();car.honk();             // "BEEP!"car.go();               // "Vroom!"car.color;              // "tan"car instanceof Car;     // truecar instanceof Vehicle; // true

Now, there’s a problem here. The Vehicle constructor only gets called once, to set up Car‘s prototype. We need to give it a color there. We can’t make different cars have different colors, which is not ideal. Some JavaScript frameworks have gotten around this by defining their own implementations of classes.

AND FOR MY LAST TRICK…

Sometimes you don’t want a notion of classes. Sometimes you just want one object to inherit the properties of another (but be able to override them). This is how most prototype-based languages work, but not JavaScript. At least, not without a little massaging.

This function lets us accomplish it. It’s been tossed around for a long time and is sometimes called “create” and sometimes “clone” and sometimes other things.

function create(parent) {  var F = function() {};  F.prototype = parent;  return new F();}var masterObject = {a: "masterObject value"}var object1 = create(masterObject);var object2 = create(masterObject);var object3 = create(masterObject);var object3.a = "overridden value";object1.a; // "masterObject value"object2.a; // "masterObject value"object3.a; // "overridden value"masterObject.a = "new masterObject value"object1.a; // "new masterObject value"object2.a; // "new masterObject value"object3.a; // "overridden value"

YOU SAID A MOUTHFUL.

The JavaScript prototype chain is a little different than how most languages work, so it can be tricky understand. It doesn’t make it any easier when JavaScript gets syntax that makes it looks more like other languages, like inheriting Java’s new operator. But if you know what you’re doing, you can do some crazy-cool things with it.

 

 

转载于:https://www.cnblogs.com/ghgyj/p/4006548.html

你可能感兴趣的文章
SQL Server---存储过程
查看>>
MySQL Performance-Schema(二) 理论篇
查看>>
搭建SSH详细步骤及相关说明
查看>>
Android IOS WebRTC 音视频开发总结(五五)-- 音视频通讯中的抗丢包与带宽自适应原理...
查看>>
Libgdx: 将Texturepacker打包的PNG图片还原成一张一张的单个的
查看>>
再议Swift操作符重载
查看>>
pc机进入android的shell
查看>>
javascript Date format(js日期格式化)
查看>>
Loadrunner中参数化实战(6)-Random+Each occurrence
查看>>
tomcatserver解析(六)-- Acceptor
查看>>
asp.net判断访问者是否来自移动端
查看>>
Python 一些常用模块的安装
查看>>
严苛模式(StrictMode)
查看>>
牛客网-《剑指offer》-跳台阶
查看>>
unity, editorWindow update计时
查看>>
我的VSTO之路(二):VSTO程序基本知识
查看>>
DataTable.Compute 性能慢的问题
查看>>
分层是一种思想
查看>>
Prime Ring Problem
查看>>
Windows系统bug
查看>>