JavaScript. The core.
Read this article in: Japanese, German (version 2), Arabic, Russian, French, Chinese.
This note is an overview and summary of the “ECMA-262-3 in detail” series. Every section contains references to the appropriate matching chapters so you can read them to get a deeper understanding.
Intended audience: experienced programmers, professionals.
We start out by considering the concept of an object, which is fundamental to ECMAScript.
An object
ECMAScript, being a highly-abstracted object-oriented language, deals with objects. There are also primitives, but they, when needed, are also converted to objects.
An object is a collection of properties and has a single prototype object. The prototype may be either an object or the null value
Let’s take a basic example of an object. A prototype of an object is referenced by the internal [[Prototype]]
property. However, in figures we will use __<internal-property>__
underscore notation instead of the double brackets, particularly for the prototype object: __proto__
.
For the code:
var foo = {
x: 10,
y: 20
};
we have the structure with two explicit own properties and one implicit __proto__
property, which is the reference to the prototype of foo
:
Figure 1. A basic object with a prototype.
What for these prototypes are needed? Let’s consider a prototype chain concept to answer this question.
A prototype chain
Prototype objects are also just simple objects and may have their own prototypes. If a prototype has a non-null reference to its prototype, and so on, this is called the prototype chain.
A prototype chain is a finite chain of objects which is used to implement inheritance and shared properties.
Consider the case when we have two objects which differ only in some small part and all the other part is the same for both objects. Obviously, for a good designed system, we would like to reuse that similar functionality/code without repeating it in every single object. In class-based systems, this code reuse stylistics is called the class-based inheritance — you put similar functionality into the class A
, and provide classes B
and C
which inherit from A
and have their own small additional changes.
ECMAScript has no concept of a class. However, a code reuse stylistics does not differ much (though, in some aspects it’s even more flexible than class-based) and achieved via the prototype chain. This kind of inheritance is called a delegation based inheritance (or, closer to ECMAScript, a prototype based inheritance).
Similarly like in the example with classes A
, B
and C
, in ECMAScript you create objects: a
, b
, and c
. Thus, object a
stores this common part of both b
and c
objects. And b
and c
store just their own additional properties or methods.
var a = {
x: 10,
calculate: function (z) {
return this.x + this.y + z;
}
}; var b = {
y: 20,
__proto__: a
}; var c = {
y: 30,
__proto__: a
}; // call the inherited method
b.calculate(30); //
c.calculate(40); //
Easy enough, isn’t it? We see that b
and c
have access to the calculate
method which is defined in a
object. And this is achieved exactly via this prototype chain.
The rule is simple: if a property or a method is not found in the object itself (i.e. the object has no such an own property), then there is an attempt to find this property/method in the prototype chain. If the property is not found in the prototype, then a prototype of the prototype is considered, and so on, i.e. the whole prototype chain (absolutely the same is made in class-based inheritance, when resolving an inherited method — there we go through the class chain). The first found property/method with the same name is used. Thus, a found property is called inherited property. If the property is not found after the whole prototype chain lookup, then undefined
value is returned.
Notice, that this
value in using an inherited method is set to the original object, but not to the (prototype) object in which the method is found. I.e. in the example above this.y
is taken from b
and c
, but not from a
. However, this.x
is taken from a
, and again via the prototype chain mechanism.
If a prototype is not specified for an object explicitly, then the default value for __proto__
is taken — Object.prototype
. Object Object.prototype
itself also has a __proto__
, which is the final link of a chain and is set to null
.
The next figure shows the inheritance hierarchy of our a
, b
and c
objects:
Figure 2. A prototype chain.
Notice: ES5 standardized an alternative way for prototype-based inheritance using Object.create function: var b = Object.create(a, {y: {value: 20}});
var c = Object.create(a, {y: {value: 30}}); You can get more info on new ES5 APIs in the appropriate chapter. ES6 though standardizes the __proto__, and it can be used at initialization of objects.
Often it is needed to have objects with the same or similar state structure (i.e. the same set of properties), and with different state values. In this case we may use a constructor function which produces objects by specified pattern.
Constructor
Besides creation of objects by specified pattern, a constructor function does another useful thing — it automatically sets a prototype object for newly created objects. This prototype object is stored in the ConstructorFunction.prototype
property.
E.g., we may rewrite previous example with b
and c
objects using a constructor function. Thus, the role of the object a
(a prototype) Foo.prototype
plays:
// a constructor function
function Foo(y) {
// which may create objects
// by specified pattern: they have after
// creation own "y" property
this.y = y;
} // also "Foo.prototype" stores reference
// to the prototype of newly created objects,
// so we may use it to define shared/inherited
// properties or methods, so the same as in
// previous example we have: // inherited property "x"
Foo.prototype.x = 10; // and inherited method "calculate"
Foo.prototype.calculate = function (z) {
return this.x + this.y + z;
}; // now create our "b" and "c"
// objects using "pattern" Foo
var b = new Foo(20);
var c = new Foo(30); // call the inherited method
b.calculate(30); //
c.calculate(40); // // let's show that we reference
// properties we expect console.log( b.__proto__ === Foo.prototype, // true
c.__proto__ === Foo.prototype, // true // also "Foo.prototype" automatically creates
// a special property "constructor", which is a
// reference to the constructor function itself;
// instances "b" and "c" may found it via
// delegation and use to check their constructor b.constructor === Foo, // true
c.constructor === Foo, // true
Foo.prototype.constructor === Foo, // true b.calculate === b.__proto__.calculate, // true
b.__proto__.calculate === Foo.prototype.calculate // true );
This code may be presented as the following relationship:
Figure 3. A constructor and objects relationship.
This figure again shows that every object has a prototype. Constructor function Foo
also has its own __proto__
which is Function.prototype
, and which in turn also references via its __proto__
property again to the Object.prototype
. Thus, repeat, Foo.prototype
is just an explicit property of Foo
which refers to the prototype of b
and c
objects.
Formally, if to consider a concept of a classification (and we’ve exactly just now classified the new separated thing — Foo
), a combination of the constructor function and the prototype object may be called as a “class”. Actually, e.g. Python’s first-class dynamic classes have absolutely the same implementation of properties/methods resolution. From this viewpoint, classes of Python are just a syntactic sugar for delegation based inheritance used in ECMAScript.
Notice: in ES6 the concept of a “class” is standardized, and is implemented as exactly a syntactic sugar on top of the constructor functions
as described above. From this viewpoint prototype chains become as an implementation detail of the class-based inheritance: // ES6
class Foo {
constructor(name) {
this._name = name;
} getName() {
return this._name;
}
} class Bar extends Foo {
getName() {
return super.getName() + ' Doe';
}
} var bar = new Bar('John');
console.log(bar.getName()); // John Doe
The complete and detailed explanation of this topic may be found in the Chapter 7 of ES3 series. There are two parts: Chapter 7.1. OOP. The general theory, where you will find description of various OOP paradigms and stylistics and also their comparison with ECMAScript, and Chapter 7.2. OOP. ECMAScript implementation, devoted exactly to OOP in ECMAScript.
Now, when we know basic object aspects, let’s see on how the runtime program execution is implemented in ECMAScript. This is what is called an execution context stack, every element of which is abstractly may be represented as also an object. Yes, ECMAScript almost everywhere operates with concept of an object
JavaScript. The core.的更多相关文章
- javascript系列之核心知识点(一)
JavaScript. The core. 1.对象 2.原型链 3.构造函数 4.执行上下文堆栈 5.执行上下文 6.变量对象 7.活动对象 8.作用域链 9.闭包 10.this值 11.总结 这 ...
- 清除css、javascript及背景图在浏览器中的缓存
在实际项目开发过过程中,页面是上传到服务器上的.而为了减少服务器的压力,让用户少加载,浏览器会将图片.css.js缓存到本地中,以便下次访问网站时使用.这样做不仅减少了服务器的压力,并且也减少了用户的 ...
- 【Web前端】清除css、javascript及背景图在浏览器中的缓存
在实际项目开发过过程中,页面是上传到服务器上的.而为了减少服务器的压力,让用户少加载,浏览器会将图片.css.js缓存到本地中,以便下次访问网站时使用.这样做不仅减少了服务器的压力,并且也减少了用户的 ...
- JS学习:JavaScript的核心
分享到 分类 JS学习 发布 ourjs 2013-12-02 注意 转载须保留原文链接,译文链接,作者译者等信息. 作者: JeremyWei 原文: JavaScript The ...
- term "JavaScript"
在Web浏览器上下文中理解的总称“JavaScript”包含几个非常不同的元素. 其中一个是核心语言(ECMAScript),另一个是Web API的集合,包括DOM(文档对象模型) JavaScri ...
- JavaScript Objects in Detail
JavaScript’s core—most often used and most fundamental—data type is the Object data type. JavaScript ...
- atitit.闭包的概念与理解attilax总结v2 qb18.doc
atitit.闭包的概念与理解attilax总结v2 qb18.doc 1.1. 闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.1 2. #---- ...
- addEventListener、attachEvent、cancelBubble兼容性随笔
一.前言 1. element.addEventListener(eventType, handler, capture); (1)参数eventType是要注册句柄的事件类型名. (2)参数hand ...
- 如何:对 SharePoint 列表项隐藏 ECB 中的菜单项
可以通过使用功能框架向编辑控制块 (ECB) 菜单添加新的自定义操作.但是,您不能使用此方法进行相反的操作,即隐藏现有的 ECB 菜单项,因为它们是通过使用 ECMAScript(JavaScript ...
随机推荐
- JavaScript高级程序设计之函数性能
setTimeout 比 setInterval 性能更好 // 取代setInterval setTimeout(function self () { // code goes here setTi ...
- ios各种手势,很有意思
转自http://blog.csdn.net/likendsl/article/details/7554150 这哥们很厉害的 一.概述 iPhone中处理触摸屏的操作,在3.2之前是主要使用的是由U ...
- LNMP下wordpress无法切换主题,只显示当前主题解决方法
最近在lnmp下发现wordpress后台无法切换主题,只能显示当前主题,开始还以为是文件没传完,又重置了一遍,还是一样.百度得知,原来军哥的LNMP安装包默认关闭了scandir函数,为了安全考虑. ...
- ABAP自定义类的构造方法
REPORT ytest_011. *----------------------------------------------------------------------* * CLASS z ...
- 字符串比较 忽略大小写 iphone
//不考虑大小写比较字符串1 NSString *astring01 = @"this is a String!"; NSString *astring02 = @"Th ...
- java获取常见文本文件的编码 解决乱码问题
乱码问题的产生一般是,由字节流转字符流的时候,读文件的编码与文件的系统编码不一致造成的. 解决方式:先自动判断文件系统编码类型,然后读的时候用这个类型去读就ok了. 自动判断文件系统编码类型代码如下, ...
- 20145120《Java程序设计》课程总结
20145120<Java程序设计>课程总结 每周读书笔记链接汇总 寒假学习总结 第1周学习总结 第2周学习总结 第3周学习总结 第4周学习总结 第5周学习总结 第6周学习总结 第7周学习 ...
- Eclipse中的常用快捷键
快捷修复 Command+1 //int a=100L; //int a=(int) 100L; 快捷删除行 Command+D 快速起新行 Shift+Enter (当本行代码很长时,将光标定在本行 ...
- 【First Missing Positive】cpp
题目: Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2 ...
- Android中的单位及测试相关概念
android中的单位: in 英寸 pt 点距 px 像素 dp(dip) 密度无关的像素单位,自适应device屏幕的比例,通常涉及长宽高时采用 sp 与范围无关的像素单位,通常在设置字体大小时 ...