Learning notes on JavaScript types, prototypes and inheritance

Time:2021-10-19


What is in this note:

✔️ A minimalist introduction to JavaScript
✔️ Simple sorting of data types in JavaScript
✔ Object oriented principle in JavaScript

There is nothing in this note:

❌ Specific syntax of JavaScript
❌ Other features implemented by JavaScript through various built-in objects


1、 Overview

  • Interpretive, orJust in time compiledLanguage.
  • Multi paradigm dynamic language, which supports functional programming natively and object-oriented programming through prototype chain.
  • In fact, it is completely different from Java. The design refers to the data structure and memory management of Java and the basic syntax of C language, but the concept is not similar.
  • At first, it was a scripting language specially designed for browsers, but now it is also used in many other environments, and can even be executed in any device equipped with a JavaScript engine.

2、 Data type

1. Data types in JavaScript

In the latest standard, 8 data types are defined. These include:

  • There are 7 basic types: number, string, Boolean, bigint, null, undefined, and the new symbol in es2016.
  • 1 complex type: object.

2. What is a basic data type

2.1 concept

Basic data types, and some versions are also translated into original data types.

What is the basic type? Take a look at the definitions given on the MDN:

In JavaScript, a primitive (primitive value, primitive data type) is data that is not an object and has no methods.

Basic types are the lowest level types, not objects, and have no methods.

The values of all basic data types cannot be changed – you can assign a new value to a variable and overwrite the original value, but you cannot directly modify the value itself.

This is very intuitive for number and Boolean, but for strings, you may need to pay special attention: a string in the same block of memory cannot be partially modified, but must be reassigned as a whole.

var a = "hello"; //  A variable of type string with the value "hello"
  console.log(a); // hello
  console.log(typeof a); // string
  a[0] = "H"; 
  console.log(a); // hello
  var c = a; // world
  c = c + " world"; //  Here, instead of changing the original Hello, a new memory space is opened up and a new basic value "Hello world" is constructed
  console.log(c); // hello world

2.2 seven basic types

  • Boolean
    • Value istrueandfalse
    • 0""NaNnullundefinedWill also be converted tofalse
  • Null
    • Null type has only one value:null。 Represents an undeclared value.
    • Note: for historical reasons, the result of typeof null is"object"
  • undefined
    • Uninitialized value (declared but not assigned).
var a;
	console.log(typeof a); // undefined
	console.log(typeof a);  // "undefined"
  • Number
    • 64 bit double precision floating-point number (there is no difference between integer and floating-point number).
  • Large integer bigint
    • Integers can be expressed with any precision.
    • Create by appending n to the end of an integer or calling the constructor.
    • It cannot be mixed with number, and a type error will be reported. Conversion is required first.
  • String string
    • Unicode character sequence.
  • Symbol
    • The value that can be used as the key of an object (private by default).
    • adoptSymbol()Function construction, each symbol value returned from the function is unique.
    • You can use an optional string to describe a symbol, which is only equivalent to a comment and can be used for debugging.
var sym1 = Symbol("abc");
	var sym2 = Symbol("abc");
	console.log(sym1 == sym2); // false
	console.log(sym1 === sym2); // false

2.3 basic type encapsulation object

After contacting some JavaScript code and understanding its classification of types, you may be very confused: the basic data type is not an object and there is no method, so why do you often see calling methods for variables of “basic types” such as strings and numbers?

For example:

var str = "hello";

console.log(typeof str); // string
console.log(str.charAt(2)); // "l"

As you can see, the type of STR is indeed the basic typestringIn theory, it is not an object. But we can actually call some methods defined for strings through dot operators. Why?

Actually, executionstr.charAt(2)A lot of things happened during the call, which is much more complex than the “ordinary call” we see.

There is the concept of basic type wrapper classes in Java. For example:IntegerIt’s basicintType, which provides some additional functions.

In JavaScript, the principle is the same, but it is hidden in form. In JavaScript, native objects are definedString, as the basic typestringofEncapsulated object。 What we seecharAt()Method is actually a definition in a string object. When we try to access the properties and methods of the basic type, JavaScript will automatically encapsulate an encapsulated object for the basic type value, and then access the properties and methods from the encapsulated object. And this object istemporary, the wrapper object will be discarded after calling the property.

This explains one thing: why adding attributes to a basic type will not report an error, but it will not have any effect. Because the added attribute is actually added to the temporary object, and the temporary object is quickly destroyed without affecting the original value.

The encapsulated objects are:StringNumberBooleanandSymbol

We can also explicitly create wrapper objects through new (exceptSymbol)。

var str = "hello";
var num = 23;
var bool = false;
var S = new String(str)
var N = new Number(num)
var B = new Boolean(bool);
console.log(typeof S); //object
console.log(typeof N); // object
console.log(typeof B); // object

Generally speaking, it is better to entrust this matter to the JavaScript engine. Manually creating encapsulated objects may cause many problems.

As a technical implementation detail, wrapper object does not need too much attention. But understanding this principle will help us better understand and use basic data types.

3. What is an object type

3.1 four types of special objects

  • Function
    • Every JavaScript function is actually aFunctionobject
    • In JavaScript,The function is “first class citizen”That is, a function can be assigned to a variable, can be used as a parameter, and can be used as a return value. (this feature is also available in Lua)
    • Therefore, a function can be understood as an ordinary object attached with a callable function.
  • Array array
    • The global object used to construct the array. An array is an object of a kind list.ArrayThe length of the element is variable and the element type is arbitrary, so it may be non dense. Array index can only be an integer. The index starts from 0
    • The element is accessed through brackets
    • Date date
    • adoptnewOperator creation
  • Regular regexp
    • Used to match text to a pattern

3.2 an object is a collection of attributes

Object is a kind of special data, which can be regarded as a set of attributes. Properties can be data or functions (called methods at this time). Each attribute has a name and a value, which can be approximately regarded as a key value pair. The name is usually a string or a stringSymbol

3.3 object creation

var obj = new Object(); //  Through the new operator
var obj = {}; //  Through object literal

3.4 access to objects

There are two ways to access the properties of an object, one through the point operator and the other through brackets.

var a = {};
a["age"] = 3; //  Add new attribute
console.log(a.age); // 3
for(i in a){
  console.log(i); // "age"
  console.log(a[i]); // 3
}

For the method of an object, if parentheses are added, the call result is returned; If you do not add parentheses, it is the return method itself, which can be assigned to other variables.

var a = {name : "a"};
a.sayHello = function(){
  console.log(this.name + ":hello");
}
var b = {name : "b"};
b.saySomething = a.sayHello;
b.saySomething(); //"b:hello"

Note: when a function is called as a method of an object, the value of this is the object.

3.5 reference type

In some places, the concept of reference type is used to refer to object type. To understand this statement, you need to understand how variables are accessed in JavaScript.

  • Values of basic data types are accessed by value

  • Values of reference types are accessed by reference

Access by value means that the value is immutable, the comparison is the comparison between values, and the identifier and value of variables are stored in stack memory. During assignment, the value is copied. After assignment, the two variables do not affect each other.

Access by reference means that the value is variable (the attribute of the object can be dynamically added, deleted and modified), the comparison is the comparison of references (two different empty objects are not equal), the value of the reference type is saved in the heap memory, and the address is saved in the stack memory. During assignment, the address value is copied. After the copy operation, the two variables point to the same object. If an object property is modified through one of the variables, it has also been changed to access the property through another variable.

3.6 comparison with table in Lua

The concept of object type is similar to that of table type in Lua. Variables are saved by references, and data organization is in the form of class key value pairs. Table uses the original table to realize the object-oriented concept, and JavaScript uses the prototype.
At present, there are many similarities, and the differences need to be further compared.

3、 Object oriented

1. Significance

There is often a need for reuse in programming. We hope to build objects with the same structure on a large scale. Sometimes we also hope to build new objects based on an existing object, and only rewrite or add some new properties. This requires the concept of “type and inheritance”.

There is no class implementation in JavaScript. Except for the basic type, there is only object. However, we can implement object-oriented requirements through prototype inheritance.

Note: ecmascript6 introduces a new set of keywords to implement class. But the underlying principle is still based on prototype. Not here.

2. Prototype and inheritance

In JavaScript, each object has a special hidden attribute[[Prototype]], it’s eithernull, or a reference to another object. The referenced object is called the prototype object of this object.

Prototype objects also have their own[[Prototype]], layer by layer up until the prototype object of an object isnull

It can be easily inferred that this is a chain, or tree relationship.nullThere is no prototype. It is the end of all prototype chains.

As mentioned earlier, an object in JavaScript is a collection of attributes. The prototype attribute concatenates multiple obejects into a chain. When trying to access the attribute of an object, it will first search in the object. If it is not found, it will search all the way along the prototype chain until the attribute is found on a prototype or reaches the end of the prototype chain. JavaScript is implemented in this forminherit

From the perspective of principle, it is natural to understand that the attributes at the front end of the prototype chain will shield the attributes with the same name at the back end.

Functions are first-class citizens in JavaScript. The inheritance of functions is no different from that of other attributes.

It should be noted that when calling a methodobj.method()Even if the method is fromobjFrom the prototype of,thisAlways referenceobj。 Method is always used with the current object.

3. Custom object

How to create similar objects

Inheriting an object can pass through the prototype, so how to generate the object reusable?

We can use functions to simulate the “class” we want. Implement a constructor like function in which we define and return the object we want. In this way, each time we call this function, we can generate a new object of the same “class”.

function makePerson(name, age){
    return {
        name: name,
        age: age,
        getIntro:function(){
            return "Name:" + this.name + " Age:" + this.age;
        };
    };
}
var xiaoming = makePerson("Xiaoming", 10);
console.log(xiaoming.name, xiaoming.age); // "Xiaoming" 10
console.log(xiaoming.getIntro()); // "Name:Xiaoming Age:10"

keywordthis, when used in a function, it always refers to the current object — that is, the object that calls the function.

Constructor and new

We can usethisAnd keywordsnewTo further encapsulate the constructor.

keywordnewYou can create a new empty object, use this of the new object to call the function, andthisReturn value as a function. We can do this in a functionthisSet properties and methods.

In this way, our function is a function that can cooperatenewTo use the real constructor.

Usually constructors do notreturnsentence. If soreturnStatement and returns an object, it will be replaced by this objectthisreturn. If it isreturnIs the original value, it is ignored.

function makePerson(name, age){
    this.name = name;
    this.age = age;
    this.getIntro = function(){
        return "Name:" + this.name + " Age:" + this.age;
    };
}
var xiaoming = new makePerson("Xiaoming", 10);
console.log(xiaoming.name, xiaoming.age); // "Xiaoming" 10
console.log(xiaoming.getIntro()); // "Name:Xiaoming Age:10"

Prototype attribute of constructor

The above implementation can produce the custom object we want, but it is different from that in C + +classThere is also a big disadvantage of the ratio: each object contains duplicate function objects. However, if we implement this function outside, we will add unnecessary global functions.

JavaScript provides a powerful feature. Each function object has aprototypeProperty that points to an object. adoptnewThe new object created willprototypeProperty is assigned to its own[[Prototype]]Properties. That is, every one passesnew The object generated by the constructor function, its[[Prototype]]All point to the current of the constructor functionprototypeThe object pointed to.

Note that the functionprototypeProperties and the previously mentioned hidden[[Prototype]]Attributes are not the same thing.

Function objectprototypeIs a common attribute called “prototype”, which does not point to the prototype of the function object. The prototype of the function object is saved in the[[Prototype]]Yes.

In fact, every function object can be seen as passingnew Function()Constructed, that is, each function object[[Prototype]]Properties are defined byFuntionofprototypeAttribute assignment.

We define the function object by defaultprototypeIs an empty object. We can dynamically affect all objects based on this object (that is, all objects generated from this function) by changing the properties of this empty object.

So the above example can be rewritten as:

function makePerson(name, age){
    this.name = name;
    this.age = age;
}
var xiaoming = new makePerson("Xiaoming", 10);
makePerson.prototype.getIntro = function(){
    return "Name:" + this.name + " Age:" + this.age;
};
console.log(xiaoming.name, xiaoming.age); // "Xiaoming" 10
console.log(xiaoming.getIntro()); // "Name:Xiaoming Age:10"

Here is the object constructed firstxiaoming, a new method is added to its prototype. As you can see,xiaomingYou can call the newly defined prototype method through the prototype chain.

It should be noted that if you directly make the functionprototypeFor new objects, it will not affect the previously generated inheritors – because of their[[Prototype]]Saved in is the originalprototypeA reference to the object pointed to.

4、 Reference

MDN | reintroduce JavaScript
MDN | Primitive
Prototype inheritance
MDN | prototype and rendering chain

Recommended Today

Swift advanced (XV) extension

The extension in swift is somewhat similar to the category in OC Extension can beenumeration、structural morphology、class、agreementAdd new features□ you can add methods, calculation attributes, subscripts, (convenient) initializers, nested types, protocols, etc What extensions can’t do:□ original functions cannot be overwritten□ you cannot add storage attributes or add attribute observers to existing attributes□ cannot add parent […]