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  // true
vehicle 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; // true
vehicle instanceof FuzzyBear // false
vehicle 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关键字,所以会提供工厂方法,但是这个时候就必须担心类型比较的问题:

<script type="text/javascript">
function Foo() {
}
var foo = new Foo();
console.log(foo instanceof Foo);//true function Foo2(){
function InnerFoo2(){ }
return new InnerFoo2();
}
var foo2 = new Foo2();
console.log(foo2 instanceof Foo2);//false function Foo4(){}
function Foo3(){
function InnerFoo3(){ }
// InnerFoo3.prototype.constructor = Foo3;
return new InnerFoo3();
}
var foo3 = new Foo3();
console.log(foo3 instanceof Foo3);//false
console.log(foo3.constructor);//true function Foo4(){}
function Foo5(){
function InnerFoo5(){ }
InnerFoo5.prototype = new Foo4();
return new InnerFoo5();
}
var foo5 = new Foo5();
console.log(foo5 instanceof Foo4);//true
</script>

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; //

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; //

But if we like, we can always override it.

vehicle.wheelCount = 8;
vehicle.wheelCount //
(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 / constructor
var Vehicle = function Vehicle(color) {
// Initialization
this.color = color;
} // Instance methods
Vehicle.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; // true
car 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.

<script type="text/javascript">
function Father(){
this.name = 'father name';
}
Father.prototype.get_name = function(){
return this.name;
}
function Son(){ }
Son.prototype = new Father();
var son = new Son();
son.name = 'son name';
console.log(son.get_name());//测试一下覆盖了父类的属性之后的表现
delete son.name
console.log(son.get_name()); </script>

JavaScript constructors, prototypes, and the `new` keyword的更多相关文章

  1. JavaScript Constructors

    Understanding JavaScript Constructors It was: 1) This article is technically sound. JavaScript doesn ...

  2. 图解Javascript原型链

    本文尝试阐述Js中原型(prototype).原型链(prototype chain)等概念及其作用机制.上一篇文章(图解Javascript上下文与作用域)介绍了Js中变量作用域的相关概念,实际上关 ...

  3. [Javascript] ES6 Class Constructors and the Super Keyword

    When the ES6 class shipped back in 2015, a number of additional keywords came with it. Two of these ...

  4. [Javascript] The "this" keyword

    The very first thing to understand when we're talking about this-keyword is really understand what's ...

  5. javascript 私有方法的实现

    原文地址: http://frugalcoder.us/post/2010/02/11/js-classes.aspx Classy JavaScript - Best Practices 11. F ...

  6. You Don't Know JS: this & Object Prototypes (第6章 Behavior Delegation)附加的ES6 class未读

    本章深挖原型机制. [[Prototype]]比类更直接和简单! https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%2 ...

  7. A re-introduction to JavaScript (JS Tutorial) 转载自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

    A re-introduction to JavaScript (JS Tutorial) Redirected from https://developer.mozilla.org/en-US/do ...

  8. 我也谈javascript闭包

    1.什么是闭包呢?Whenever you see the function keyword within another function, the inner function has acces ...

  9. How do JavaScript closures work?

    Like the old Albert Einstein said: If you can't explain it to a six-year-old, you really don't under ...

随机推荐

  1. Android初步 简单demo

    刚入门不久,没学JAVA,从C++转过来的,C++的QT和安卓简直有异曲同工之妙,为了加深自己对安卓的理解,特写博客以记录,望大神们多多指点. 效果图,刚入门的话,肯定要熟悉基本的控件的使用,这跟我学 ...

  2. 几个不常见但非常出色的 .NET 开源库

    NLog NLog 目前最为出色的 .NET 日志库,非常容易配置,且极具灵活性.最重要的是与 log4net 相比,NLog 的开发很活跃.顺带提一句,NLog 完全兼容 Mono. Mono.Ce ...

  3. 【转】spring3 MVC实战,手工搭建Spring3项目demo

    更新:这几天对spring3的理解又进了一步,今天抽空把这篇文章中的错误和不当之处做了修改. 最近的项目在用Spring3,涉及到了基于注解的MVC,事务管理,与hibernate的整合开发等内容,我 ...

  4. codeforces 390C Inna and Candy Boxes

    这个题目看似不是很好下手,不过很容易发现每次询问的时候总是会问到第r个盒子是否有糖果: 这样的话就很好办事了: 维护两个数组: 一个sum数组:累加和: 一个in数组:如果i位是1的话,in[i]=i ...

  5. WAF 与 RASP 的安装使用大比拼!

    什么是WAF和RASP? WAF全称是Web application firewall,即 Web 应用防火墙.RASP 全称是 Runtime Application Self-protect,即应 ...

  6. 如何将CELERY放到后台执行?

    在作正式环境,这个是必须的. 于是找了两小时文档, 以下这个方法,相对来说好实现. 就是要注意supervisord.conf的目录存放位置. 放在DJANGO的PROJ目录下,是最佳位置. http ...

  7. 上海CEC大收购(包括华大九天)

    紫光收购展讯.锐迪科后,上海开始通过扶植CEC培育新势力,CEC已经收购上海澜起,即将收购amlogic.Ominivision,还在与marvell眉来眼去,此外华大九天已经移植上海,加上之前的上海 ...

  8. 131. Palindrome Partitioning

    题目: Given a string s, partition s such that every substring of the partition is a palindrome. Return ...

  9. leetcode面试准备: Word Pattern

    leetcode面试准备: Word Pattern 1 题目 Given a pattern and a string str, find if str follows the same patte ...

  10. (?m)

    centos6.5:/root/sbin#cat -n vv 1 192.168.11.186,192.168.11.187 35199,3306 Dec 7, 2016 11:40:02.75052 ...