object 一词有很多意义,一般任意的“东西”都可以称为对象,但有时又有特殊的含义。这里我们用object
专指javascript中类型为Object
的对象,而用 object 表示普通意义下的对象。
Object
Every variable can be used as (but not is) an object
, except for undefined and null . Even number literal has its dot operation if the dot is not parsed as float point.
2.toString(); // SyntaxError
2..toString(); // valid
2 .toString(); // valid
(2).toString(); //valid
However, javascript distinguish Object
data types (including function object and array object) from primary data types (Number, String, …)
var a = 3;
a.x = 2; //invalid, a.x is undifiend
var b = [3, 2];
b.x = 2; //valid
function foo(){}
foo.x = 2; //valid
var c = {}
c.x = 2; //valid
var s = "str";
s.x = 2; //invalid
object
can be used as hash tables. A property can be accessed in two ways: dot operation and [] operation. They are equivalent, except that [] operation can be used in following two cases while dot operation can’t:
- set property dynamiclly
- property name is a not valid variable name
Objects created using {} are inherited form Object.prototype. A property can only be deleted using delete
operation
object
有两种,一种是function, 一种是其它。
- 一方面function可以看作普通的
object
,f instance Function
- 另一方面funciton可以看作类,它是
Object
的子类 (Object同时又是一个function), 可以用f.prototype instanceof Object
验证 - 每个
object
都有一个__proto__
属性指向prototype chain上一级。属性prototype则只有function才有。function hi(name){
console.log("hi",name)
}
console.log(hi instanceof Function) // true
console.log(hi instanceof Object) // true
console.log(Function instanceof Object) //true
console.log(Function.prototype instanceof Object) //true
console.log(hi.prototype) // {}
console.log(Function.prototype) // {}
Usage of this
this can only be used inside of function, it always refers to the caller of this function.
this may refers to global
this in constructor functionvar x = 1;
function test(){
alert(this.x);
}
test(); // 1
this in bound function: apply, callvar x = 2;
function test(){
this.x = 1;
}
var o = new test();
alert(x); //2
alert(o.x); //1
var x = 0;
function test(){
alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m.apply(); //0
o.m.apply(o); //1
Prototypal inheritance
Most Javascript implementations use__proto__
property to represent the next object in the prototype chain.
We need to distinguish__proto__
fromprototype
Everyobject
(include function object) has an implicit__proto__
property. It is this property that implements prototype chain.function getProperty(obj, prop) {
if (obj.hasOwnProperty(prop))
return obj[prop]
else if (obj.__proto__ !== null)
return getProperty(obj.__proto__, prop)
else
return undefined
}
Note: The
in
,for in
operations will search upward the prototype chain, usehasOwnProperty
as filter if needed.hasOwnProperty
is the only thing in JavaScript which deals with properties and does not traverse the prototype chain.
A “constructor” in JavaScript is “just” a function that happens to be called with the new operator.
Every constructor function has a property prototype, which is an empty object by default. If variable x is constructed (using new) by function F, then x.__proto__ === F.prototype
Here is how new works:
function New (F) {
var n = { '__proto__': f.prototype };
return function () {
F.apply(n, arguments);
return n;
};
}
3. x = new f()
doesn’t implement “x inherits another object”. However, Douglas Crockford found a way to exploit the new operator to do real Prototypal Inheritance!
Object.create = function (parent) {
function F() {}
F.prototype = parent
return new F()
};
- Instance object (object that is not function) don’t have prototype (undefined). This prototype has a constructor property. Whenever a constructor’s prototype is manually modified, its constructor should be maintained properly. ( to ensure the correctness of operations like
this.constructor.prototype.constructor.prototype
andinstance of
)function Animal() {
`this.species = "动物";
}
The code above implement that “Cat inherit Animal”, which is actually “cat1 inherits new Animal()”function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
- Not standard: __proto__ is non-standard and even deprecated. Also native Object.create and Douglas Crockford implementation are not exactly equivalent.
- Not optimized: Object.create (native or custom) has not yet been as heavily optimized as the new construction. It can be up to 10 times slower. ```
Class
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
The class keyword is introduced in ES6, but is syntactical sugar, JavaScript remains prototype-based.
Classes in JS are built on prototypes but also have some syntax and semantics that are not shared with ES5 classalike semantics.
Classes are in fact “special functions”, and just as you can define function expressions and function declarations, the class syntax has two components: class expressions and class declarations.
An important difference between function declarations and class declarations is that function declarations are hoisted and class declarations are not.
The body of a class is executed in strict mode, i.e., code written here is subject to stricter syntax for increased performance, some otherwise silent errors will be thrown, and certain keywords are reserved for future versions of ECMAScript.
class中涉及到三种 object
- class 本身是一个 (constructor) function, static 表示定义在这个function上,
- 通过new构建的是该class的 instance, class中的 (nonstatic) fields 和 constructor中的this 都表示定义在instance上
- 该 function有一个prototype, nonstatic (instance) method 是定义在function 的 prototype上
static/nonstatic methods/data properties 都有 public 和 private 之分this
在static method中指的是 class本身,在 instance method 中指的是instance
Methods
Class 有两种 method, 一种是 prototype method, 相当于定义在 function 的 prototype. 另一种是 static method, 相当于定义在 funciton 本身上。
The static keyword defines a static method for a class. Static methods are called without instantiating their class and cannot be called through a class instance. Static methods are often used to create utility functions for an application.
In order to call a static method within another static method of the same class, you can use the this keyword. Static methods are not directly accessible using the this keyword from non-static methods. You need to call them using the class name
Data
Class 有三种 data properties: Instance properties must be defined inside of class methods. Static (class-side) data properties and prototype data properties must be defined outside of the ClassBody declaration.
Field declaration
There are static fileds and instance fields.
Private fields can only be declared up-front in a field declaration. Fields without initializers are initialized to undefined.
Subclassing
class A extends B
意味着
Object.getPrototypeOf(A) === B
Object.getPrototypeOf(A.prototype) === B.prototype
Species
Mix-ins
A function with a superclass as input and a subclass extending that superclass as output can be used to implement mix-ins in ECMAScript:
References:
Javascript – How Prototypal Inheritance really works (by vjeux)
原型继承 (by 廖雪峰)
Javascript继承机制的设计思想 (by 阮一锋)
Javascript面向对象编程(二):构造函数的继承 (by 阮一锋)
Prototypal inheritance