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.

  1. 2.toString(); // SyntaxError
  2. 2..toString(); // valid
  3. 2 .toString(); // valid
  4. (2).toString(); //valid

However, javascript distinguish Object data types (including function object and array object) from primary data types (Number, String, …)

  1. var a = 3;
  2. a.x = 2; //invalid, a.x is undifiend
  3. var b = [3, 2];
  4. b.x = 2; //valid
  5. function foo(){}
  6. foo.x = 2; //valid
  7. var c = {}
  8. c.x = 2; //valid
  9. var s = "str";
  10. 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才有。
    1. function hi(name){
    2. console.log("hi",name)
    3. }
    4. console.log(hi instanceof Function) // true
    5. console.log(hi instanceof Object) // true
    6. console.log(Function instanceof Object) //true
    7. console.log(Function.prototype instanceof Object) //true
    8. console.log(hi.prototype) // {}
    9. 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
    1. var x = 1;
    2. function test(){
    3.   alert(this.x);
    4. }
    5. test(); // 1
    this in constructor function
    1. var x = 2;
    2. function test(){
    3.   this.x = 1;
    4. }
    5. var o = new test();
    6. alert(x); //2  
    7. alert(o.x); //1
    this in bound function: apply, call
    1. var x = 0;
    2. function test(){
    3.   alert(this.x);
    4. }
    5. var o = {};
    6. o.x = 1;
    7. o.m = test;
    8. o.m.apply(); //0
    9. 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__ from prototype
    Every object (include function object) has an implicit __proto__ property. It is this property that implements prototype chain.
    1. function getProperty(obj, prop) {
    2. if (obj.hasOwnProperty(prop))
    3. return obj[prop]
    4. else if (obj.__proto__ !== null)
    5. return getProperty(obj.__proto__, prop)
    6. else
    7. return undefined
    8. }

    Note: The in, for in operations will search upward the prototype chain, use hasOwnProperty 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:

  1. function New (F) {
  2. var n = { '__proto__': f.prototype };
  3. return function () {
  4. F.apply(n, arguments);
  5. return n;
  6. };
  7. }

object oriented - 图1
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!

  1. Object.create = function (parent) {
  2. function F() {}
  3. F.prototype = parent
  4. return new F()
  5. };
  1. 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 and instance of)
    1. function Animal() {    
    2. `this.species = "动物";  
    3. }
    1. function Cat(name, color) {    
    2. this.name = name;    
    3. this.color = color;  
    4. }
    5. Cat.prototype = new Animal();
    6. Cat.prototype.constructor = Cat;
    7. var cat1 = new Cat("大毛","黄色");
    8. alert(cat1.species); // 动物
    The code above implement that “Cat inherit Animal”, which is actually “cat1 inherits new Animal()”
    • 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