When code exhibits regular repetition, functions can be utilized, variables defined, and methods called, eliminating the need to repeatedly modify the code; only the function needs to be changed. Almost all high-level languages support functions, and JavaScript is no exception. It can be used like a variable, making it convenient and powerful. Therefore, this article systematically studies JS functions and includes detailed notes and examples throughout the learning process.
1. Definition and Calling of Functions#
1. Defining Functions#
function abs(x) {
if(x = 0) {
return x;
} else {
return -x;
}
}
function()
indicates that this is a function definition.abs
is the name of the function.(x)
contains the parameters of the function.{...}
contains the function body, which can include several statements, or even 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 in the form of a function.
var abs = function (x) {
if (x >= 0) {
return x
} else {
return -x
}
};
function(x)
is an anonymous function, which is assigned to the variable abs
, so it can be called directly through abs
.
These two ways of defining functions are completely consistent, but when defining with a variable, it is important to end with
;
to indicate the end of the function statement.
2. Calling Functions#
To call a function, simply pass the parameters.
abs(10), according to the function definition, substitutes 10 in, and the returned result is 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 written inside a function will output to the console.
First, write a loop to output the parameters, and after writing 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 in parameters
str("name", "age");
// Console output: name, age
5. return#
When returning true, clicking the link will directly jump; when returning false, it will ignore the a link's address and jump 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#
To save the excess parameters passed in as an array, to obtain additional parameters, start with i = 2 to exclude the existing a, 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);
The console prints:
You can see that the excess part is printed into the Array
.
This writing is somewhat cumbersome; below is a simpler way.
Directly define the parameter rest
in the function and add ...
in front to indicate that the excess parameters are directly given to the variable rest
as an array. You can obtain all parameters without arguments
.
If the number of passed parameters does not exceed the defined number of 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 output 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 commonly used to declare variables, and the declared variables actually have scope.
- 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.
-
If two functions each declare
variable a
, they do not interfere with each other and can function normally within their own function bodies; outside the function bodies, they have no effect. -
JS functions can be nested; 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 in son()
, and according to functions cannot access internal variables from outside
, y
cannot be accessed, hence var z = x + y
reports an error.
- Two nested function bodies, each with a variable of the same name, when JS looks for a variable, it first checks from itself. If it has that variable, it retrieves it; if not, it looks 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()
andpar()
.
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, it does not hoist the assignments, which can easily lead to code errors.
Therefore, to address this issue, when declaring variables, we should place them all at the beginning of the function, strictly adhering to the principle of declaring all variables at the start of the function
.
3. Global Scope#
Variables defined outside of 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 for 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 the inside out. If it is still not found in the global scope, a ReferenceError
will be thrown.
4. Local Scope#
The scope inside a function is local scope; the name of this code only works 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#
-
Global variables: Can be used anywhere; global variables are only destroyed when the browser is closed, which consumes more memory resources.
-
Local variables: Can only be used within the function; when the code block they are in is executed, they will be initialized; when the code block execution is completed, they will be destroyed, thus saving memory space.
-
When operating on a variable within a function scope, it will first look for it in its own scope. If found, it will use it directly; if not, it will look in the upper scope. If it is not found in the global scope either, an error will be thrown.
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.
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 is nested, destructuring assignment can also be performed, but be careful to maintain consistency with the nesting levels of 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. You can also destructure assignment for 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.
When destructuring assignment for objects, nesting can also be performed.
5. You can redefine a variable name when assigning by property name.
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:
You can see that name, age, and id are 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 like true 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, you 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 methods 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 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 throughthis
.
If the method is written outside the object, the pointing of this
needs careful analysis. For example:
function getage() {
var year = new Date().getFullYear();
return year - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getage
};
When getage()
is called alone, it 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 ofobj.xxx()
.
If this method is not used, all will report 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 pointing of this
will again have issues; it points to the first layer of the method instead of 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();
As you can see, by defining var that = this
, and then using that.
in the method to point to properties, it will not throw errors regardless of how many layers of methods there are, 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, one thing to note is that each method must return a result after it ends,
return getbirthage()
.
3. apply#
In addition to var that = this
, you can also control the pointing of this
through 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 this pointing
, i.e., the object, and the second parameter represents the parameters of the function itself.
4. apply() and call()#
call()
is a method similar to apply
, with the difference being:
apply()
packs parameters into anArray
.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 yield the same result, binding this
to null
when calling a regular function.