zishu's blog

zishu's blog

一个热爱生活的博主。https://zishu.me

javascript - Functions, Variables, and Methods

When there is a regular repetition in the code, functions can be utilized, variables can be defined, and methods can be called without needing to repeatedly modify the code; only the function needs to be modified. Almost all high-level languages support functions, and JavaScript is no exception. It can be used like a variable, which is convenient and powerful. Therefore, this article systematically studies JS functions and includes detailed notes and examples during the learning process.

1. Definition and Calling of Functions#

1. Defining Functions#

function abs(x) {
    if(x = 0) {
        return x;
    } else {
        return -x;
    }
}
  1. function() indicates that this is a function definition.
  2. abs is the name of the function.
  3. (x) contains the parameters of the function.
  4. {...} contains the function body, which can include several statements, or it can have no statements at all.

The function body must end with return to return a result; if it does not end with return, it will return undefined.

You can also directly define an object, which can also be written as a function:

var abs = function (x) {
    if (x>=0) {
        return x
    }else {
        return -x
    }
};

function(x) is an anonymous function, and this function is assigned to the variable abs, so it can be called directly through abs.

These two ways of defining functions are completely equivalent, but when defining with a variable, it is necessary to end with ; to indicate the end of the function statement.

2. Calling Functions#

When calling a function, simply pass the parameters:
abs(10), according to the function definition, substituting 10 will return the result x, which is 10.

3. Checking Parameters#

You can check the parameters to see if they are of the desired type.

If a non-number is passed to the parameter abs(x), the console will return this is not number. If a number is passed, it will perform a conditional check.

function abs(x) {
    // Check if parameter x is a number
    if (typeof x !== 'number') {
        console.log('this is not number')
    }else{
        if (x >= 0) {
            return x
        }else {
            return -x
        }
    }
}

4. arguments#

Using arguments, you can obtain all parameters passed by the caller.

arguments represents the passed parameters, and arguments.length represents the length of the passed parameters.

console.log(arguments.length)
// This line of code should be written inside a function to output to the console.

First, write a loop to output the parameters, and after completing the function, pass in parameters, and the console will print the passed parameters accordingly.

function str() {
    var s
    for(var i = 0; i<arguments.length; i++) {
        // Return the passed parameters
        console.log(arguments[i]);
        s += arguments[i] + ",";
    }
    return s;
};
// Pass parameters
str("name", "age");
// Console output: name, age

5. return#

When returning true, clicking the link will directly redirect; when returning false, it will ignore the a link's address and redirect to the address after window.location.href.

<a href="https:www.baidu.com" onclick="return myfun()">baidu</a>
<input type="text" id="test" value="click">
<script>
    function myfun() {
    window.location.href = 'https://www.bilibili.com';
    var test = document.getElementById('test').value;
    console.log(test);
    
    return false;
}
</script>

Points to note about return: The function will automatically add ; at the end of the line, so when writing return, be careful not to simply split it into two lines, as it can easily cause errors.

return 
    { name: 'foo' }
// The above writing is problematic; JS's mechanism will automatically render it as
return;     //return undefined
    { name: 'foo' };

// The correct way should be:
return {
    name: 'foo'
};

6. rest#

The extra parts of the passed parameters are saved in an array format. To obtain additional parameters, start with i = 2 to exclude the already existing a and b.

function arr(a, b) {
    var i, rest = [];
    if (arguments.length > 2) {
        
        for (i = 2; i<arguments.length; i++) {
            rest.push(arguments[i]);
        }
    }
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
};

arr(1,2,3,4);

Console prints:
image

You can see that the extra parts are printed into the Array.

This writing is somewhat cumbersome; below is a simpler way to write it.

Directly define the parameter rest in the function and prefix it with ..., so that the extra parameters are directly given to the variable rest in array form, without needing arguments to obtain all parameters.

If the number of parameters passed does not exceed the number of defined parameters, the function will return an empty array.

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest)
}

foo(1,2,3,4)
// a = 1
// b = 2
// Array [3,4]

foo(1)
// a = 1
// b = undefined
// Array [ ] 

7. Calculation#

Sum the passed parameters

// forEach can return all elements in the array

function sum(...rest) {
    var sum = 0;
    rest.forEach(function(x) {
        sum += x;
    });
    return sum;
};

//sum(1,2)
// Console outputs 3. Sum successful

Calculate the area of a circle

// r represents the radius of the circle
// pi defaults to 3.14 if no parameter is provided
function area_of_circle(r, pi){
    var area;
    if(arguments.length == 1) {
        // When only one parameter is passed, calculate 3.14*r squared
        area = 3.14*r*r;
    }else{
        area = pi*r*r;
    }
    return area;
}

2. Variables and Scope#

1. Declaring Variables#

In JS, var is typically used to declare variables, and the declared variables actually have scope.

  1. Variables declared within a function body can only take effect within that function body and cannot be recognized outside of it.
function fun() {
    var a = 1;
};
a = a + 1;  // err  This line of code directly reports an error because there is no variable a in the global scope.
  1. If each function body declares a variable a, they do not interfere with each other and can function normally within their respective function bodies, but have no effect outside of them.

  2. JS functions can be nested, and inner functions can access outer functions, but outer functions cannot access inner functions.

function par() {
    var x = 1;
    function son() {
        var y = x + 1;
    };
    var z = x + y;      // Error:
}

Thus, var z = x + y will report an error because variable y is within son(), and according to functions cannot access inner variables from outside, y cannot be accessed, hence var z = x + y results in an error.

  1. If two nested function bodies each have a variable with the same name, JS functions prioritize searching for variables from within themselves. If the variable exists, it is used; if not, it searches outward from lower to upper levels.
function par() {
    var num = 1;
    function son() {
        var num = 2;
        console.log("son() = " + num);
    };
    console.log("par() = " + num);
    son();
};
par();

Functions must be called to take effect: son() and par().

2. Variable Hoisting#

JavaScript function definitions have a characteristic: they first scan all statements in the function body and "hoist" all declared variables to the top of the function. However, assignments are not hoisted, which can easily lead to code errors.

Therefore, to address this issue, we should uniformly place variable declarations at the start of the function, strictly adhering to the principle of declaring all variables at the beginning of the function.

3. Global Scope#

Variables defined outside any function are called global variables, which exist under window. They are also referred to as global scope. Variables in the global scope are actually bound to window.

var course = 'learn js';
console.log(course);        // learn js
console.log(window.course)  // learn js

Directly accessing global variables or prefixing with window yields the same result.

There is only one global scope in the entire JS file, which is window. If a variable is not found in a certain function scope, it will be searched layer by layer from inner to outer. If it is still not found in the global scope, a ReferenceError will be thrown.

4. Local Scope#

The scope within a function is called local scope; the variable name only takes effect within the function.

In statements like for loops, it is not possible to define variables with local scope.

5. Differences Between Global and Local Variables#

  1. Global variables: Can be used anywhere; global variables are only destroyed when the browser is closed, consuming more memory resources.

  2. Local variables: Can only be used within the function; when the code block they are in is executed, they are initialized; once the code block execution is complete, they are destroyed, thus saving memory space.

  3. When operating on a variable within a function scope, it first searches in its own scope. If found, it is used directly; if not, it searches in the upper scope. If it is not found in the global scope either, an error will be reported.

6. Constants#

var and let declare a variable, while using uppercase variable names indicates defining a constant.

// ES5
var NAME = 'xiaoming'

ES6 introduces a new keyword const to define constants.

// ES6
const name = 'xiaoming'

3. Destructuring Assignment#

1. You can assign elements of an array to different variables separately.

var array = ['hello', 'javascript', 'ES6'];
var x = array[0];
var y = array[1];
var z = array[2];

// x = 'hello'
// y = 'javascript'
// z = 'ES6'

2. If the array itself has nesting, destructuring assignment can also be performed, but the nesting levels must match the array.

let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];

x; // 'hello'
y; // 'JavaScript'
z; // 'ES6'

3. Elements can be ignored during destructuring assignment.

let [, , z] = ['hello', 'JavaScript', 'ES6'];

z;  // ES6 

4. Destructuring assignment can also be applied to objects.

var person = {
    name: 'xiaoming',
    age: 22,
    gender: 'male',
    email: '[email protected]',
    school: 'zyg'
}
// Three variables are defined, corresponding to three properties
var {name, age, email} = person;
console.log(name, age, email);

The console can print out the desired content.

image

When destructuring assignment for objects, nesting can also be performed.

5. You can redefine a variable name when assigning through property names.

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
};

// Assign the passport property to the variable id:
let {name, passport:id} = person;
console.log(name);
console.log(age);
console.log(id);
console.log(email);

Console output results:

image

You can see that name, age, and id are all printed out, while email throws an error because the content of email was assigned to the new variable id, and email has no content, hence the error.

6. You can use default values to avoid returning undefined for non-existent properties.

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678'
};

// If the person object does not have a single property, default to true:
var {name, single=true} = person;
name;   // '小明'
single; // true

Note that when assigning, it cannot start with { to avoid rendering failure in JS.

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678'
};
// Declare variables
var x;
var y;

// Destructuring assignment
{x, y} = { name: '小明', x: 100, y: 200} // Error:

Here, {x, y} = person will throw an error because = is illegal. So the correct way is to wrap the assignment statement in parentheses:

({x, y} = { name: '小明', x: 100, y: 200});

7. Use Cases for Destructuring Assignment

Swapping the values of two variables:

var a = 1;
var b = 2;
[a, b] = [b, a]

4. Methods of Objects#

Functions bound to objects are called methods.

Binding functions within an object is referred to as a method of that object.

1. this#

The following code returns (current year - birth year):

var xm = {
    name: 'xiaoming',
    birth: 1998,
    age: function() {
        var year = new Date().getFullYear();
        return year - this.birth
    }
};
// In object xm, call the method age()
xm.age();   // 22

This introduces a new keyword this.

Within a method, this is a special variable that always points to the current object, which is the variable xm.

Thus, this.birth refers to the birth property of variable xm.

this exists within methods; to call an object's properties within a method, it must be done through this.

If the method is written outside the object, the this pointing issue needs to be analyzed. For example:

function getage() {
    var year = new Date().getFullYear();
    return year - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getage
};

image

When calling getage() alone, getage() refers to a method, and since this method is in the global scope, this points to the global object window, resulting in NaN.

Only calling xiaoming.age() invokes the method getage() under the object xiaoming.

Therefore, to ensure the correct pointing of this, it must be called in the form of obj.xxx().
If this method is not used, all will throw errors; if in 'use strict' mode, this will point to undefined.

2. that#

If a method within an object has another layer of events, the this pointing issue arises again; it points to the first layer of the method rather than the corresponding object.

Thus, when writing methods, first declare var that = this, which points to the properties within the object. Then, when calling properties within the method, simply prefix with that. to directly point to the properties under the object.

var xm = {
    name: 'xiaoming',
    birth: 1998,
    age: function() {
        var that = this;
        function getbirthage() {
            var y = new Date().getFullYear();
            return y - that.birth;
        }
        return getbirthage();
    }
};

// xm.age();

image

As you can see, by defining var that = this, and then using that. to point to properties within the method, it will not throw errors regardless of how many layers of methods are nested, directly pointing to the properties under the object.

By using var that = this, you can confidently define other functions within the method without worrying about not being able to access object properties.

However, it is important to note that each method must return a result after completion, return getbirthage().

3. apply#

In addition to var that = this, you can also control the pointing of this using the apply property.

apply is a method of the function itself and has two parameters.

function getage() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xm = {
    name: 'xiaoming',
    birth: 1998,
    age: getage
}

// xm.age();
// getage.apply(xm, []);

The syntax is getage.apply(xm, []), where the first parameter of apply represents the this pointing, i.e., the object, and the second parameter represents the parameters of the function itself.

image

4. apply() and call()#

call() is a method similar to apply, with the difference being:

  1. apply() packages parameters into an Array.
  2. call() directly passes parameters in order.

Calling math.max(1,2,3) can be done in both ways:

math.max.apply(null, [1,2,3]);  // 3
math.max.call(null, 1, 2, 3);    // 3

Both methods yield the same result, binding this to null when calling a regular function.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.