JavaScript minimalism tutorial ii: objects and functions

  • 2020-03-30 04:10:33
  • OfStack

Reading this article requires programming experience in other languages.

Simple types in JavaScript include:

1. Digital
2. The string
3. Boolean (true and false)
4. Null
5. Undefined

Other types are objects (let's not get confused by the return value of the typeof operator), such as:

1. The function
An array of 2.
3. Regular expressions
4. Objects (objects are objects, of course)

Object based

In JavaScript, an object is a collection of attributes (an associative array of objects), each of which includes:

1. Property name, must be a string
2. Property value, which can be any value except undefined

Create an object with object literal:


//Create an empty object
with the object literal {} var empty_object = {};

Object property name and property value:


var stooge = {
    //"First-name" is the property name and "Jerome" is the property value
    "first-name": "Jerome",
    //"Last-name" is the property name and "Howard" is the property value
    "last-name": "Howard"
};

If the attribute name is a valid identifier, the quotes can be omitted:


var flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
    },
    arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    }
};

Let's look at an example of property access:


var owner = { name: "Name5566" };
 
owner.name; // "Name5566"
owner["name"]; // "Name5566"
 
owner.job; // undefined
owner.job = "coder"; //Or owner["job"] = "coder"; < br / >

If the attribute name is not a valid identifier, you need to wrap it in quotes. The value of a nonexistent property is undefined. Objects are passed by reference rather than by value:


var x = {};
var owner = x;
owner.name = "Name5566";
x.name; // x.name === "Name5566"

Here x and owner refer to the same object.

Properties of an object can be deleted using the delete operator:


delete obj.x; //Delete the x attribute of object obj

Prototype of an object

Each object is linked to a prototype object, which can inherit properties from the prototype object. We create an Object with Object literal, whose prototype Object is the object.prototype Object (the object.prototype Object has no prototype Object of its own). When we create an object, we can set the prototype object of the object (we'll talk about that later). When trying to get (rather than modify) a property of an Object, JavaScript tries to get the property from the prototype Object of the Object if the Object does not exist, and if the prototype Object does not have the property, it looks from the prototype Object of the prototype Object, and so on, until the object.prototype Object. When we modify a property of an object, we do not affect the prototype object, as opposed to getting a property.

Basis function

In JavaScript, functions are also objects that link to the function.prototype prototype Object (function.prototype links to object.prototype). The function has a property called prototype, whose value is of type object. This object has a property constructor, whose value is the function:


var f = function() {}
 
typeof f.prototype; // 'object'
typeof f.prototype.constructor; // 'function'
 
f === f.prototype.constructor; // true

Functions are objects, you can use functions as objects, that is, functions can be stored in variables, arrays, can be passed as arguments to functions, functions can be defined internally. Incidentally, functions have two hidden properties:

1. Function context
2. Function code

The function is created as follows:


var f = function add(a, b) {
    return a + b;
}
 
console.log(f); //Output [Function: add]

The name of the function after the keyword function is optional. We make the name of the function mainly for several purposes:

1. For recursive calls
2. Used to identify functions by debuggers, development tools, etc

A lot of times we don't need a function name, a function that doesn't have a function name is called an anonymous function. Enclosed in parentheses is the parameter list. JavaScript should not match arguments with parameters, for example:


var add = function(a, b) {
    return a + b;
}
 
add(1, 2, 3); //Arguments and parameters do not match

If there are too many arguments, the extra arguments are ignored, and if there are too few arguments, the value of an unassigned parameter is undefined. The function must have a return value, and if the return value is not specified by the return statement, the return value of the function is undefined.

A function and the external variables it accesses form a closure. This is the key attraction of JavaScript.

A function call

When each function is called, it receives two additional arguments:

1. This
2. The arguments

The value of this depends on the mode of invocation. There are four modes of invocation in JavaScript:

1. Method invocation pattern. An object's properties are called methods if they are functions. If a method is called through o.m(args), this is object o (thus, this and o are bound when called), for example:


var obj = {
    value: 0,
    increment: function(v) {
        this.value += (typeof v === 'number' ? v : 1);
    }
};
obj.increment(); // this === obj

2. Function call mode. If a function is not a property of an object, it is called as a function, and this is bound to the global object, for example:


message = 'Hello World';
var p = function() {
 console.log(this.message);
}
 
p(); //Output 'Hello World'

This behavior can sometimes be confusing. Here's an example:


obj = {
    value: 0,
    increment: function() {
        var helper = function() {
            //Add 1
to the value in the global object             this.value += 1;
        }
 
        //The helper is called as a function to
        //So this is a global object
        helper();
    }
};
 
obj.increment(); // obj.value === 0

The desired outcome should be:


obj = {
    value: 0,
    increment: function() {
        var that = this;
        var helper = function() {
            that.value += 1;
        }
 
        helper();
    }
};
 
obj.increment(); // obj.value === 1

3. Constructor call pattern. A function that intends to use the new prefix is called a constructor, for example:


//Test is called the constructor
var Test = function(string) {
    this.message = string;
}
 
var myTest = new Test("Hello World");

A function can be called by adding new (such a function usually begins with an uppercase), adding new creates an object that links to the function's prototype property, and this is the object in the constructor.

4. Apply invocation pattern. The apply method of the function is used to call the function, which has two arguments, the first is this, the second is an array of arguments, for example:


var add = function(a, b) {
    return a + b;
}
 
var ret = add.apply(null, [3, 4]); // ret === 7

When the function is called, we can access an array of classes called arguments (not a real JavaScript array) that contains all arguments, so we can implement variable length arguments:


var add = function() {
    var sum = 0;
    for (var i=0; i<arguments.length; ++i) {
        sum += arguments[i];
    }
    return sum;
}
 
add(1, 2, 3, 4);

abnormal

Now for JavaScript's exception-handling mechanism. We use the throw statement to throw the exception, and the try-cache statement to catch and handle the exception:


var add = function (a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        //Throws an exception
        throw {
            name: 'TypeError',
            message: 'add needs numbers'
        };
    }
    return a + b;
}
 
//Catch and handle exceptions
try {
    add("seven");
//E is the exception object thrown
} catch (e) {
    console.log(e.name + ': ' + e.message);
}

Add attributes for JavaScript types

Most types in JavaScript have constructors:

1. The constructor of the Object is Object
2. The constructor of Array is Array
The constructor of the Function is Function
4. The constructor of a String is String
5. The Number constructor is Number
The Boolean constructor is a Boolean
7. The constructor of the regular expression is RegExp

We can add a property (often a method) to the constructor prototype to make this property available to related variables:


Number.prototype.integer = function() {
    return Math[this < 0 ? 'ceil' : 'floor'](this);
}
 
(1.1).integer(); // 1

scope

JavaScript USES functions to build scopes:


function() {
    // ...
}();


var obj = function() {
    //Hidden value, external cannot access
    var value = 0;
 
    return {
        //This method can modify value
        increment: function() {
            value += 1;
        },
        //This method can read value
        getValue: function() {
            return value;
        }
    };
}();
 
obj.increment();
obj.getValue() === 1;

inheritance

There are many ways to implement inheritance in JavaScript.
When creating an object, we can set the prototype object associated with the object. We do this:


//Create an object o whose prototype object is {x:1, y:2}
var o = Object.create({x:1, y:2});

The object.create method is defined in ECMAScript 5. If you use ECMAScript 3, you can implement a create method yourself:


//If the object.create method
is not defined if (typeof Object.create !== 'function') {
    //Object. Create method
    Object.create = function (o) {
        var F = function () {};
        F.prototype = o;
        //Creates a new object with the prototype object o
        return new F();
    };
}

With the object.create method we do prototype-based inheritance: a new Object directly inherits the properties of an old Object (as opposed to class-based inheritance, where there is no need for the class to exist, the Object directly inherits the Object). Example:


var myMammal = {
    name: 'Herb the Mammal',
    get_name: function() {
        return this.name;
    },
    says: function() {
        return this.saying || '';
    }
};
 
//Inheritance myMammal < br / > var myCat = Object.create(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'meow';
myCat.purr = function(n) {
    var i, s = '';
    for (i = 0; i < n; i += 1) {
        if (s) {
            s += '-';
        }
        s += 'r';
    }
    return s;
};
myCat.get_name = function() {
    return this.says() + ' ' + this.name + ' ' + this.says();
};

The code above is simple, but it doesn't protect private members. We can use the module pattern. In module mode, a class of objects is generated by a function that USES a function scope to protect private members from external access:


//The verb function, which is used to construct a verb object
var mammal = function(spec) {
    //That is the constructed object
    var that = {};
 
    //The public method get_name can be accessed externally
    that.get_name = function() {
        //
cannot be accessed directly from outside spec.name         return spec.name;
    };
 
    //The public method says can be accessed externally
    that.says = function() {
        //< br / > cannot be accessed from outside of spec.saying         return spec.saying || '';
    };
 
    return that;
};
 
//Create a mammal object
var myMammal = mammal({name: 'Herb'});
 
//Cat function, used to construct the cat object
var cat = function(spec) {
    spec.saying = spec.saying || 'meow';
 
    //Cat inherits from a mammal, so first construct a
object     var that = mammal(spec);
 
    //Add the public method purr
    that.purr = function(n) {
        var i, s = '';
        for (i = 0; i < n; i += 1) {
            if (s) {
                s += '-';
            }
            s += 'r';
        }
        return s;
    };
 
    //Modify the public method get_name
    that.get_name = function() {
        return that.says() + ' ' + spec.name +
            ' ' + that.says();
        return that;
    };
};
 
//Create a cat object
var myCat = cat({name: 'Henrietta'});

In the module pattern, inheritance is implemented by calling the constructor. In addition, we can also access the methods of the parent class in the subclass:


Object.prototype.superior = function(name) {
    var that = this, method = that[name];
    return function() {
        return method.apply(that, arguments);
    };
};
 
var coolcat = function (spec) {
    //Gets the get_name method of the subclass
    var that = cat(spec), super_get_name = that.superior('get_name');
    that.get_name = function(n) {
        return 'like ' + super_get_name() + ' baby';
    };
    return that;
};


Related articles: