JavaScript Concepts and Comparisons Guide
JavaScript Concepts and Comparisons Guide
JavaScript vs Java
JavaScript vs Typescript
Babel
Webpack
Prototype
ES5 vs ES6
JavaScript Variables: Global and local variables
JavaScript Variables: Variable shadowing
JavaScript Variables: Non-strict mode
JavaScript Variables: strict mode
JavaScript Variables: hoisting
JavaScript Variables: var, let, const
Primitive data types
String Built-in Methods
Object
Object Array
Spread operator to copy [… test1]
Callback function
() ⇒ {} / () ⇒ () function
==(loose equality) vs ===(strict equality)
Function declarations, hoisting
Function: The arguments object
DOM manipulation
Selecting elements
Manipulating elements
Working with Events - Ways to create event
Events Flow - Events Bubbling(default)
Events Flow - Event capturing
Event Object - Properties and Methods
Event Delegation
JavaScript Advanced Topic - Anonymous Functions
JavaScript Advanced Topic - immediately invoked function IIFE /ˈɪfi/
Closure ppt105 -108
Closure + asynchronous
Currying Function
JavaScript 1
JavaScript Advanced Topic - Passing by value(primitive data types)
JavaScript Advanced Topic - Passing by value of object(objects)
call(), apply() and bind()
Promise
Async and await
Event Loop
this
JavaScript vs Java
Java is considered a compiled programming language, while JavaScript is
considered an interpreted scripting language
Java uses static type checking, and JavaScript uses dynamic typing
JavaScript 2
you must declare the data type of a variable explicitly when you
define it. Once the data type is declared, it cannot be changed during
the execution of the program. The Java compiler enforces strong type
checking, meaning it checks for type compatibility at compile-time,
ensuring that only operations that are valid for the declared types are
allowed. If there is a type mismatch or an incompatible operation, the
compiler raises an error, and the program must be fixed before it can be
executed.
Example of static typing in Java:
JavaScript 3
let age = 30; // Declaration of a variable 'age' with
an integer value
let name = "John"; // Declaration of a variable 'nam
e' with a string value
JavaScript 4
The event loop is responsible for processing events and executing
asynchronous tasks, such as user interactions, timers, and network
requests.
class Animal {
void makeSound() {
[Link]("Some generic animal so
und.");
}
}
JavaScript 5
void makeSound() {
[Link]("Bark!");
}
}
const animalPrototype = {
makeSound() {
[Link]("Some generic animal sound.");
}
};
JavaScript 6
JavaScript (JS) and TypeScript are both languages used for web development,
but they have some important differences:
JavaScript (JS):
2. Dynamic Typing: It is dynamically typed, which means you can change the
type of a variable at runtime and the interpreter won't know the type of the
variable until the code is running.
5. Flexibility: It can be very flexible, but this can also lead to less predictable
code, which might be full of surprises due to its dynamic nature.
TypeScript:
3. Tooling: The type system allows for better tooling, including more powerful
autocomplete, navigation, and refactoring features.
JavaScript 7
codebases or teams.
8. Error Catching: TypeScript’s type system helps catch errors early in the
development process, which can lead to more robust, cleaner code.
Babel is a JavaScript compiler that lets you use ES6+ code in older
browsers. It's commonly used in modern web development projects to
ensure compatibility across different browsers. To configure Babel, you
typically work with a .babelrc file (or [Link] in more recent
versions). Here's a brief guide to setting up and configuring Babel:
1. Installing Babel:
If you're starting from scratch, you'll want to set up a new project with
npm:
JavaScript 8
2. Babel Presets & Plugins:
Babel uses "presets" and "plugins" to determine how to transform your
code. A preset is a set of plugins bundled together.
For example, to transform ES6+ code to ES5:
{
"presets": ["@babel/preset-env"]
}
3. Transforming Code:
With the CLI installed and the preset set, you can now compile your
ES6+ code:
This command will take the JavaScript files from the src directory and
compile them to ES5 in the dist directory.
4. React Configuration:
If you're using React, you'll want to add the Babel preset for React:
{
"presets": ["@babel/preset-env", "@babel/preset-rea
JavaScript 9
ct"]
}
5. Other Configurations:
You might come across the need for other plugins or presets based on
what features you're using. For instance, if you want to use
async/await, you might need the @babel/plugin-transform-runtime and
@babel/runtime .
Always refer to the Babel documentation or specific plugin/preset
documentation for additional setup details.
If you're using a module bundler like Webpack or Rollup, they have their
own Babel integrations, like babel-loader for Webpack. This lets you
integrate Babel into the bundling process.
Babel is a widely used JavaScript compiler that allows you to write JavaScript
code using the latest ECMAScript features and then transpile (convert) that
code into an older version of JavaScript that is compatible with most browsers
and environments. This is particularly useful because it allows developers to
take advantage of new language features without worrying about whether they
are supported in all browsers.
JavaScript 10
your terminal. Then, you can initialize a new [Link] project if you haven't
already by running:
npm init -y
{
"presets": ["@babel/preset-env"]
}
JavaScript 11
npx babel [Link] -o [Link]
<script src="[Link]"></script>
Babel is a powerful tool for modern JavaScript development, and it can greatly
improve your ability to write code using the latest language features while
maintaining compatibility with older browsers.
Webpack
Webpack is a static module bundler for JavaScript applications. When
Webpack processes your application, it internally builds a dependency graph
which maps every module your project needs and generates one or more
bundles. Over the years, Webpack has grown and can now transform front-end
assets like HTML, CSS, and images, if the corresponding plugins are included.
JavaScript 12
1. Entry
An entry point indicates which module Webpack should use to begin
building out its internal dependency graph. Webpack will figure out which
other modules and libraries that entry point depends on (directly and
indirectly).
[Link] = {
entry: './path/to/my/entry/[Link]'
};
2. Output
The output property tells Webpack where to emit the bundles it creates and
how to name these files. It defaults to ./dist/[Link] for the main output file
and to the ./dist folder for any other generated file.
[Link] = {
output: {
filename: '[Link]',
path: __dirname + '/dist'
}
};
3. Loaders
Webpack only understands JavaScript and JSON files. Loaders allow
Webpack to process other types of files and convert them into valid
modules that can be consumed by your application and added to the
dependency graph.
[Link] = {
module: {
rules: [
{ test: /\\.txt$/, use: 'raw-loader' },
{ test: /\\.css$/, use: ['style-loader', 'css-load
er'] },
JavaScript 13
// and so on for other file types like .scss, .les
s, .ts, etc.
]
}
};
4. Plugins
While loaders are used to transform certain types of modules, plugins can
be leveraged to perform a wider range of tasks like bundle optimization,
asset management, and injection of environment variables.
[Link] = {
plugins: [new HtmlWebpackPlugin({ template: './src/ind
[Link]' })]
};
5. Mode
By setting the mode parameter to either development , production , or none , you
can enable Webpack's built-in optimizations that correspond to each
environment.
[Link] = {
mode: 'production'
};
6. DevServer
Webpack provides a development server that can be used to quickly
develop applications. It provides live reloading out of the box, among other
features.
JavaScript 14
[Link] = {
devServer: {
contentBase: './dist',
hot: true
}
};
7. Source Maps
Webpack can generate source maps, which is a way to map your compiled
code back to your original source code. This is extremely helpful for
debugging your application.
[Link] = {
devtool: 'inline-source-map'
};
8. Code Splitting
Webpack allows you to split your codebase into multiple chunks. Code
splitting can be used to load parts of the application on demand and can
significantly improve performance.
9. Tree Shaking
This is a feature provided by Webpack that is used to remove unused code
from your bundle, helping to keep the bundle size down.
JavaScript 15
Here's a basic guide to setting up and configuring Webpack:
1. Installing Webpack:
2. Basic Configuration:
[Link] = {
mode: 'development',
entry: './src/[Link]',
output: {
filename: '[Link]',
path: [Link](__dirname, 'dist'),
},
};
output : Where to emit the bundles it creates and how to name them.
3. Loaders:
JavaScript 16
Loaders allow Webpack to process other types of files and convert them
into valid modules.
For example, to handle CSS, you'd use css-loader to interpret @import and
url() and style-loader to inject CSS into the DOM:
module: {
rules: [
{
test: /\\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
4. Plugins:
Plugins can be leveraged to perform a wider range of tasks like bundle
optimization, asset management, and injection of environment variables.
For instance, to manage HTML files, you can use html-webpack-plugin :
Update [Link] :
//...
JavaScript 17
5. Dev Server:
Update [Link] :
devServer: {
contentBase: './dist',
},
6. Other Configurations:
'inline-source-map' .
Always refer to the official Webpack documentation for deeper dives into
configurations and setups. The ecosystem is vast, and there are loaders,
plugins, and configurations for many common use cases.
Prototype
In JavaScript, the prototype is an inherent property of every object. It is a
mechanism that allows objects to inherit properties and methods from other
objects.
The prototype is itself an object, so the prototype will have its own prototype,
making what's called a prototype chain . The chain ends when we reach a
prototype that has null for its own prototype.
JavaScript 18
When you try to access a property of an object: if the property can't be found
in the object itself, the prototype is searched for the property. If the property
still can't be found, then the prototype's prototype is searched, and so on until
either the property is found, or the end of the chain is reached, in which
case undefined is returned.
ES5 vs ES6
function example() {
if (true) {
var x = 5;
}
[Link](x); // outputs 5
}
function example() {
if (true) {
let y = 5;
const z = 10;
}
[Link](y); // ReferenceError: y is not defined
[Link](z); // ReferenceError: z is not defined
}
2. Arrow Functions
ES5: Functions are typically written using the function keyword.
JavaScript 19
// ES5
var add = function(x, y) {
return x + y;
};
// ES6
const add = (x, y) => x + y;
3. Promises
ES5: Callbacks were predominantly used for asynchronous operations.
4. Classes
ES5: In ES5, developers emulated class-like behavior using constructor
functions and prototypes.
// ES5
function Car(make) {
[Link] = make;
}
[Link] = function() {};
// ES6
class Car {
constructor(make) {
[Link] = make;
}
drive() {}
}
JavaScript 20
ES6 introduces shorthand for property methods and defines properties.
5. Template Literals
ES5: In ES5, developers concatenated strings using the + operator.
// ES5
var str = "Hello, " + name + "!";
// ES6
let str = `Hello, ${name}!`;
JavaScript 21
7. Destructuring
ES6 introduces destructuring assignment.
8. Modules
ES5: No native module system. Relied on third-party solutions like
CommonJS or AMD.
There are many other improvements and additions in ES6 compared to ES5.
These differences mark a significant evolution of the language, making
JavaScript more powerful and developer-friendly.
JavaScript Variables: Global and local variables
In JavaScript, all variables exist within a scope that determines the lifetime of
the variables and which part of the code can access them.
Scope determines the accessibility (visibility) of variables.
JavaScript 22
Block scope
Function scope
Global scope
Before ES6 (2015), JavaScript had only Global Scope and Function Scope for
var .
Block scope
{
let x = 2;
}
// x can NOT be used here
However:
Variables declared with the var keyword can NOT have block scope.
Variables declared inside a { }(curly brackets) block can be accessed from
outside the block.
{
var x = 2;
}
// x CAN be used here
Local scope
Variables declared within a JavaScript function, become LOCAL to the
function. Local variables have Function Scope. They can only be accessed
JavaScript 23
from within the function.
function myFunction() {
let carName = "Volvo";
// code here CAN use carName
}
Since local variables are only recognized inside their functions, variables
with the same name can be used in different functions.
Local variables are created when a function starts, and deleted when the
function is completed.
Function scope
Variables declared with var , let and const are quite similar when declared
inside a function. They all have Function Scope:
function myFunction() {
var carName = "Volvo"; // Function Scope
}
function myFunction() {
let carName = "Volvo"; // Function Scope
}
JavaScript 24
function myFunction() {
const carName = "Volvo"; // Function Scope
}
Global Scope
JavaScript 25
With the var keyword in JavaScript, variable shadowing can occur, but
there's a unique behavior to consider. Variables declared with var are
function-scoped, not block-scoped. This means that a variable declared
with var inside structures like for loops or if statements doesn't create a
new scope, unlike variables declared with let or const .
Here's an example of shadowing using var :
function exampleFunction() {
var x = 20; // inner scope variable, shadows the outer
x
[Link](x); // This will output 20, not 10
}
exampleFunction();
[Link](x); // This will output 10
var x = 10;
if (true) {
var x = 20; // Despite being inside an if statement, t
his is in the same scope as the outer x
[Link](x); // This will output 20
}
overwrites the outer x . This is one of the potential pitfalls of using var , and
JavaScript 26
a reason many developers have moved to using let and const , which
provide block-level scoping.
For example, we have two variables that share the same name: message. The
first message variable is a global variable whereas the second one is the local
variable. Inside the say() function, the global message variable is shadowed. It
cannot be accessible inside the say() function but outside of the function. This
is called variable shadowing.
// global variable
var message = "Hello";
function say() {
// local variable
var message = 'Hi’;
[Link](message);
// which message?
}
say();// Hi
[Link](message); // Hello
JavaScript 27
In this code, the message variable is not explicitly declared, so it becomes a
global variable. That's why it is accessible both inside and outside the say()
function, and its value is retained after the function call.
function say() {
message = 'Hi’;
[Link](message);
// which message?
}
say();// Hi
[Link](message); //Hi
JavaScript 28
// Equivalent to:
// var x;
// [Link](x);
// x = 5;
When executing JavaScript code, the JavaScript engine goes through two
phases:
Parsing/ˈpɑːrsɪŋ/
Execution
The var keyword has been available in JavaScript since its early versions.
The user can re-declare(reassign) the variable using var and the user
can update the var variable.
JavaScript 29
var a = 10
// Output: 7
var variables are also hoisted (meaning they are moved to the top of
their scope during the execution phase).If users use the var variable
before the declaration, it initializes with the undefined value.
[Link](a); // undefined
var a = 10;
let
Scope: block scoped: The scope of a let variable is only block scoped.
It can’t be accessible outside the particular block ({block}).
From ES6, you can use the let keyword to declare one
or more variables. The let keyword is similar to the
var keyword. However, a variable is declared using the
let keyword is block-scoped, not function or global-
scoped like the var keyword.
Users cannot re-declare the variable defined with the let keyword but
can update it.
JavaScript 30
the same scope, you cannot declare it again with let (or const ).
Doing so will result in a syntax error.
2. Users can update it: Variables declared with let are mutable,
meaning their values can be changed after they've been initialized.
If users use the let variable before the declaration, it does not initialize
with undefined just like a var variable, and returns an error.
const
Scope: block scoped: When users declare a const variable, they need
to initialize it, otherwise, it returns an error. The user cannot update
the const variable once it is declared.
The const keyword has all the properties that are the same as
the let keyword, except the user cannot update it. cannot re-declare
const a = {
prop1: 10,
prop2: 9
JavaScript 31
}
// It is allowed
a.prop1 = 3
// It is not allowed
a = {
b: 10,
prop2: 9
}
The scope of
The scope of a let variable is The scope of a const variable
a var variable is
block scope. is block scope.
functional scope.
It can be updated
It can be updated but cannot It cannot be updated or re-
and re-declared
be re-declared into the scope. declared into the scope.
into the scope.
It can be declared
It can be declared without It cannot be declared without
without
initialization. initialization.
initialization.
It can be accessed
It cannot be accessed without It cannot be accessed without
without initialization
initialization otherwise it will initialization, as it cannot be
as its default value
give ‘referenceError’. declared without initialization.
is “undefined”.
JavaScript 32
JavaScript has six primitive data types:
• null
• undefined
• boolean
• number
• string
• symbol – available only from ES6
Immutable
undefined
The undefined type is a primitive type that has one value undefined.
By default, when a variable is declared but not initialized, it is assigned the
value undefined.
let counter;
[Link](counter); // undefined
[Link](typeof counter); // undefined
null
The null type is the second primitive data type that also has only one value:
null
number
JavaScript 33
• Integer numbers
• Floating-point numbers
• NaN: which stands for Not a Number. In fact, it means an invalid number
[Link](Number(0.1 + 0.2).toFixed(1));
String
In JavaScript, a string is a sequence of zero or more characters. A literal
string begins and ends with either a single quote(‘) or a double quote (“).
You can use literals `` to represent string as well.
JavaScript 34
Let greeting = `HI`
let message = `Hello ${name}`;
Boolean
The boolean type has two values: true and false, in lowercase.
To convert a value of another data type into a boolean value, you use the
Boolean function.
[Link](Boolean('Hi'));// true
indexOf()
split()
JavaScript 35
split() divides a string into an array of substrings:
split([separator], [limit]);
includes()
[Link](searchString [,position])
slice()
The slice() method returns a substring from the startIndex to the endIndex
in the str
FYI, [startIndex, endIndex), the startIndex is inclusive, and the endIndex is
exclusive. We have the same built-in methods in Array.
Object
In JavaScript, an object is a collection of properties, where each property is
defined as a key-value pair.
JavaScript 36
The following example defines an empty object using the object literal form:
let person = {
firstName: 'John’,
lastName: 'Doe’
};
A property name of an object can be any string. You can use quotes around
the property name if it isn’t a valid JavaScript identifier.
For example, if you have a property first-name, you must use the quotes
such as "first-name" but firstName is a valid JavaScript identifier so the
quotes are optional.
If you refer to a non-existent property, you’ll get an undefined value as
follows:
[Link]([Link]); // undefined
Object operations
要操作对象中的信息,您可以使用以下方式:
1. 访问属性
使用点符号 .
JavaScript 37
[Link](person['lastName']); // 输出: Doe
2. 修改属性的值
直接为属性分配一个新值:
[Link] = 'Jane';
[Link]([Link]); // 输出: Jane
使用方括号 [] :
person['lastName'] = 'Smith';
[Link]([Link]); // 输出: Smith
3. 添加新属性
如果你尝试为对象中尚不存在的属性分配值,JavaScript 会为该对象创建该
属性:
[Link] = 30;
[Link]([Link]); // 输出: 30
同样,使用方括号 也可以: []
person['job'] = 'Engineer';
[Link]([Link]); // 输出: Engineer
4. 删除属性
使用 关键字:
delete
delete [Link];
[Link]([Link]); // 输出: undefined
5. 检查属性是否存在
使用 关键字:
in
JavaScript 38
if ('firstName' in person) {
[Link]('The person has a first name.');
}
6. 遍历对象的属性
使用 循环:
for...in
这些基本操作为您提供了处理和操作对象数据的方法。
create object
const person = {
firstName: "John",
lastName: "Doe",
age: 50,
JavaScript 39
eyeColor: "blue"
};
Object Array
Two ways to create an array
arrayName[index]
[Link]
[Link]('Red Sea’);
JavaScript 40
the modified array. The reference to arrayName remains the
same, but the array itself is modified.
Adding an element to the end of an array(ES6 Syntax)
[Link]('Red Sea’);
Removing an element from the end of an array and return that removed
element
[Link]();
[Link]();
JavaScript 41
[Link](seas);
[Link]('Red Sea’);
splice()
Deleting elements using JavaScript Array’s splice() method
Inserting elements using JavaScript Array splice() method
Note that the splice() method actually changes the original array. Also, the
splice() method does not remove any elements, therefore, it returns an
empty array
[Link](position, num);
[Link](position, 0 ,new_element_1,new_element_2,
// 1. Clone an array
[Link]();
JavaScript 42
// ES6 Syntax:
const newNumbers = [… numbers];
every()
Checking every array element meet requirements, return true / false
some()
Checking at least one elements meet requirements, return true / false
forEach()
execute a function on every element of an array, no return
What is the difference between for loop and forEach ?
JavaScript 43
Once you start iterating with forEach() , it will continue to
iterate over all elements in the array until it reaches the
end. Additionally, with
forEach() , you cannot specify a starting index. It always
Output:
Name: Alice, Index: 0, Array: Alice,Bob,Charlie,Dave
Name: Bob, Index: 1, Array: Alice,Bob,Charlie,Dave
Name: Charlie, Index: 2, Array: Alice,Bob,Charlie,Dave
Name: Dave, Index: 3, Array: Alice,Bob,Charlie,Dave
array refers to the array on which the forEach() method was called.
map()
Transform its elements and include the results in a new array.
What is the difference between for map and forEach ?
JavaScript 44
map() will return a new array; forEach() does not return a
value.
!!!reduce()
The reduce() method in JavaScript is used to reduce an array to a single
value by executing a provided callback function on each element of the
array. It accumulates the result of the callback function on each iteration
and returns the final accumulated value.
[Link](callback, initialValue);
[Link](sum); // Output: 15
JavaScript 45
// 1.
[Link] = function (callback, init
let accumulator = initialValue === undefined ? 0 : in
return accumulator;
};
[Link](sum); // Output: 15
// 2.
const customReducer = (array, callback, initValue) => {
let accumulator = initValue === undefined ? 0 : ini
for (let i = 0; i < [Link]; i++) {
accumulator = callback(accumulator, array[i], i
}
return accumulator;
};
JavaScript 46
[Link](sum); // Output: 15
filter()
filter() is used to create a new array containing elements from the original
array that satisfy a specified condition. It iterates over the array and applies
a callback function to each element, returning a new array with the
elements for which the callback function returns true .
Will return a new array
join()
Array join() method to concatenate all elements of an array into a string
separated by a separator
JavaScript 47
const title = ' JavaScript array join example ';
const url = [Link]().split(' ').join('-').toLowerCase(
[Link](url); // javascript-array-join-example
1. Array Spread:
When used with an array, the spread operator can expand the elements of the
array into individual elements. It is commonly used to create shallow copies of
arrays , concatenate /kənˈkæt(ə)nˌeɪt/ arrays , or pass array elements as individual
arguments to a function .
Example:
JavaScript 48
[Link](originalArray); // Output: [1, 2, 3, 4, 5]
[Link](shallowCopy); // Output: [1, 2, 3, 4, 5]
shallow copies
As you can see, the originalArray and shallowCopy are two separate
arrays, and the comparison originalArray === shallowCopy evaluates to
JavaScript 49
false .
1. Concatenating Arrays:
Here too, the arr1 , arr2 , and combinedArray are separate arrays.
1. Merging Objects:
JavaScript 50
[Link](additionalInfo === newPerson); // Output:
false
In the case of objects, the spread operator also creates new objects
with separate memory addresses.
In all these examples, the spread operator creates new instances and
does not modify the original arrays or objects. The new instances are
shallow copies or merged versions of the original data. If you need a
deep copy of an object (including nested objects), you would need to
implement custom logic or use libraries that provide deep cloning
functionality.
Concatenating/kənˈkæt(ə)nˌeɪt/ Arrays:
function addNumbers(a, b, c) {
return a + b + c;
}
JavaScript 51
[Link](sum); // Output: 6
In this example, the spread operator "spreads" the elements of the numbers
array as individual arguments when calling the addNumbers function. So, it's
equivalent to calling addNumbers(1, 2, 3) .
2. Object Spread:
When used with objects, the spread operator creates a shallow copy of the
object or merges multiple objects into a new object. It is essential to note that
the spread operator performs a shallow copy, meaning that nested objects are
still references and not deep-copied.
Example:
3. Function Arguments:
function addNumbers(a, b, c) {
return a + b + c;
}
JavaScript 52
const sum = addNumbers(...numbers);
[Link](sum); // Output: 6
Inside a function definition, the spread operator can also be used as a "rest
parameter" to collect multiple function arguments into an array.
Example:
function concatenateStrings(...strings) {
return [Link](" ");
}
The spread operator provides a concise and expressive way to work with
arrays and objects in JavaScript and is widely used in modern JavaScript
codebases for various tasks, such as array manipulation, object merging, and
function arguments handling.
Callback function
In JavaScript, a callback is a function passed into another function as an
argument to be executed later.
why use it
JavaScript is single-threaded and executes code sequentially, which
means that long-running tasks like making HTTP requests, reading files, or
database queries can block the main thread and make the user interface
unresponsive. By using callback functions, you can control the flow of
execution and ensure that these time-consuming operations happen
asynchronously, without blocking the main thread.
() ⇒ {} / () ⇒ () function
在JavaScript(特别是在ES6及之后的版本)中,箭头函数有两种不同的写法,它们
在语法和返回值上有所不同。让我详细解释一下:
JavaScript 53
1. 带大括号 的箭头函数: {}
当你使用大括号
,箭头函数就不会有隐式返回。也就是说,如果你想返回一个值,你需要显式
{}
2. 不带大括号的箭头函数:
如果你不使用
,则该函数将隐式返回表达式的结果。这种写法非常适用于简短的函数,因为
{}
它使代码更为简洁。
const example = param => param * 2;
对于你的代码中的例子:
这是一个更完整的函数,可能包含多个语句,并且没
const => {} :
有明确返回值,所以使用 是有意义的。 {}
: 这里使用的是隐式返回,
[Link]((suggestion, index) => ( ... ))
特别是当你希望直接返回JSX时(如在React组件中),这种简洁的写法很有用。
括号 用于包围返回的JSX,确保整个JSX被作为一个整体返回,而不是只返回
()
第一个元素。
希望这能帮助你理解两种写法的差异和用途!
==(loose equality) vs ===(strict equality)
In JavaScript, the operators == (loose equality) and === (strict equality) are
used for comparison between values. Here's an explanation of how they differ:
1. Loose Equality ( == ):
JavaScript 54
Example:
5 == '5' // true
The === operator compares values for equality without performing type
coercion. It checks for both value and type equality . It requires the operands
to have the same type and value to be considered equal.
Example:
In this case, the string '5' and the number 5 have different types, so the
strict equality comparison evaluates to false .
for object :
It's important to note that when comparing objects or complex data types
(arrays, objects), the equality operators ( == and === ) check for reference
equality rather than deep equality. To compare the content of objects or arrays,
you would need to implement custom comparison logic or use libraries/utilities
designed for that purpose.
Function declarations, hoisting
JavaScript 55
is a behavior in JavaScript where function declarations are
Function hoisting
moved to the top of their scope during the compilation phase, allowing them to
be called before they are actually defined in the code.
In JavaScript, you can declare functions using two main syntaxes: function
declarations and function expressions.
1. Function Declarations:
With function declarations, the entire function, including its body, is hoisted
to the top of the current scope.
This means that you can call the function before its actual declaration in
the code.
Example:
function greet() {
[Link]("Hello");
}
In the example above, the function greet() is called before its declaration,
and it still works because the function declaration is hoisted to the top of
the scope.
// var
sayHello(); // Error: sayHello is not defined
JavaScript 56
// let
sayHello(); // ReferenceError: Cannot access 'sayHello'
before initialization
In this example, the variable sayHello is hoisted to the top, but since it is
assigned a function expression, the actual function definition is not hoisted.
Hence, trying to call sayHello() before its declaration results in an error.
It's important to note that while function declarations are hoisted, variable
declarations using var , let , or const are also hoisted but with a behavior
called "variable hoisting." However, the assignment of values to variables is not
hoisted. This can lead to unexpected behavior when accessing variables
before they are assigned a value.
DOM manipulation
JavaScript 57
The Document Object Model (DOM) is an application programming interface
(API) for manipulating HTML and XML documents.
The DOM represents a document as a tree of nodes. It provides API that allows
you to add, remove, and modify parts of the document effectively.
In this DOM tree, the
document is the root node. The root node has one child which is the <html>
<html>
<head>
<title>JavaScript DOM</title>
</head>
<body>
<p>Hello DOM!</p>
</body>
</html>
Selecting elements
getElementById()
The getElementById() method allows you to retrieve an HTML element from
the document based on its id attribute.
[Link](id);
<!DOCTYPE html>
JavaScript 58
<html>
<head>
<title>Example Page</title>
</head>
<body>
<h1 id="myHeading">Hello, World!</h1>
<script>
const heading = [Link]("myHeading");
[Link] = "Updated Heading";
</script>
</body>
</html>
getElementsByName()
getElementsByTagName()
getElementsByClassName()
JavaScript 59
If you match elements by multiple classes, you need to use whitespace to
separate them like this:
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
<style>
.highlight {
background-color: yellow;
}
</style>
</head>
<body>
<p class="highlight">This paragraph will be highlighted.
<p>This paragraph will not be highlighted.</p>
<p class="highlight">This paragraph will also be highlig
<script>
const elements = [Link]("high
The return type: HTMLCollection, which means that any changes made to
the matched elements will be reflected in the collection
querySelector()
The querySelector() is a method of the Element interface. The
querySelector() allows you to find the first element that matches one or
JavaScript 60
more CSS selectors
The querySelector method returns a static NodeList.
!!!querySelector vs querySelectorAll
Manipulating elements
createElement()
appendChild()
JavaScript 61
The appendChild() method allows you to add a node to the end of the list of
child nodes of a specified parent node
[Link](childNode);
function createMenuItem(name) {
let li = [Link]('li’);
[Link] = name;
return li;
}
append()
The [Link]() method inserts a set of Node objects or
DOMString objects after the last child of a parent node:
[Link](...nodes);
<ul id="app">
<li>JavaScript</li>
</ul>
JavaScript 62
Then:
<ul id="app">
<li>JavaScript</li>
<li>TypeScript</li>
<li>HTML</li>
<li>CSS</li>
</ul>
As you can see, the additional list items for the languages 'TypeScript',
'HTML', and 'CSS' are dynamically added to the existing unordered list.
The append() method has no return value.
It means that the append() method implicitly returns undefined.
!!!append() vs appendChild()
Input: .append allows you to add multiple Node Objects(but each item
needs to be provided as a separate argument. The items are appended
one by one in the order they are specified.) while appendChild allows
only a single Node Object
textContent()
To get or set the text content of a node and its descendants, you use the
textContent property
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<div id="note">
JavaScript 63
JavaScript textContent Demo!
<span style="display:none">Hidden Text!</span>
<!-- my comment -->
</div>
<script>
let note = [Link]('note');
[Link]([Link]);
</script>
</body>
</html>
Output:
JavaScript textContent Demo!
Hidden Text!
When you set the textContent property on a node, all the node's children are
removed, and a single text node containing the new text value replaces
them.
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<div id="message">
<p>This is the initial message.</p>
<span>Additional text.</span>
</div>
<script>
let message = [Link]('message');
[Link] = 'Updated message';
</script>
</body>
JavaScript 64
</html>
Then:
<div id="message">
Updated message
</div>
innerHTML()
The innerHTML allows you to get or set the HTML content within an element.
It provides a way to access or modify the markup, including tags,
attributes, and text, of an element and its descendants.
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<div id="content">
<p>This is the initial content.</p>
<span>Additional text.</span>
</div>
<script>
let content = [Link]('content');
[Link]([Link]);
// Output: <p>This is the initial content.</p><spa
Then:
<div id="content">
JavaScript 65
<h2>Updated content</h2>
<p>New paragraph</p>
</div>
!!!innerHTML() vs textContent()
1. Both of them allow you to get or set the HTML content within an
element.
3. the innerHTML : property allows you to convert a string into HTML tags.
When set, it replaces the entire content of the element with the
specified HTML markup. textContent: When set, it replaces all child
nodes of the element with a single text node containing the specified
text.
insertBefore()
To insert a node before another node as a child node of a parent node, you
use
the parentNode.
insertBefore()
[Link](newNode, existingNode);
JavaScript 66
function insertAfter(newNode, existingNode){
[Link](newNode, existing
}
prepend()
The prepend() method inserts a set of Node objects or DOMString objects
after the first child of a parent node:
By using the spread operator ”…”, we can pass the elements of the nodes
replaceChild()
<ul id="menu">
<li>Homepage</li>
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>
let menu = [Link]('menu');
// create a new node
let li = [Link]('li');
[Link] = 'Home';
// replace the first list item
[Link](li, [Link]);
removeChild()
JavaScript 67
The childNode is the child node of the parentNode that you want to
remove.
If the childNode is not the child node of the parentNode, the method throws
an exception.
The removeChild() returns the removed child node from the DOM tree but
keeps it in the memory, which can be used later.
You can directly use: [Link](childNode);
<script>
function handleButtonClick() {
[Link]('Button clicked!');
// Additional code logic here...
}
</script>
JavaScript 68
Second, it is a timing issue. If the element is loaded fully
before the JavaScript code, users can start interacting
with the element on the webpage which will cause an
error.
2. DOM Level 0 Event Handlers: You can assign a function directly to a
specific event property of a DOM element. For example:
To remove the event handler, you set the value of the event handler
property to null:
[Link] = null;
JavaScript 69
FYI: You need to pass the same arguments as were passed to the
addEventListener(), using an anonymous event listener will not work.
Events Flow - Events Bubbling(default)
In the event bubbling model, an event starts at the most specific element and
then flows upward toward the least/liːst/ specific element.
When you click the button/ˈbʌt(ə)n/, the click event occurs in the following
order:
1. button
3. body
4. html
5. document
1. document
JavaScript 70
2. html
3. body
5. button
[Link]('click', function(event) {
[Link]([Link]);
});
JavaScript 71
!!!preventDefault() vs stopPropagation()
preventDefault()
To prevent the default behavior of an event, you use the preventDefault()
method.
For example, when you click a link, the browser navigates you to the URL
specified in the href attribute (hypertext reference), if you don't want this to
happen, you can use
preventDefault() to stop it.
[Link]('click',function(event) {
[Link]('clicked');
[Link]();
})
stopPropagation()
The stopPropagation() method immediately stops the flow of an event
through the DOM tree. However, it does not stop the browers default
behavior.
JavaScript 72
For example, if you have a click event on an <a> link element and you call
stopPropagation() within the event handler, the event will not bubble to any
parent elements, but the link will still be followed (the default behavior of a
click event on an anchor link).
If you want to prevent the default behavior, you'd need to use the
preventDefault() method:
[Link]('click', function(event) {
[Link]();
[Link]();
});
[Link]('click', function(event) {
[Link]('The button was clicked!');
[Link](); // add later
});
[Link]('click',function(event) {
[Link]('The body was clicked!');
});
Event Delegation
With event delegation/ˌdelɪˈɡeɪʃn/, you attach a single event listener to a
parent element and handle events that occur on its child elements by utilizing
event bubbling. This is useful when you have dynamic or large numbers of
elements.
JavaScript 73
[Link]('Button clicked!');
}
});
To handle the click event of each menu item, you may add the corresponding
click event handlers: not good
<ul id="menu">
<li><a id="home">home</a></li>
<li><a id="dashboard">Dashboard</a></li>
<li><a id="report">report</a></li>
</ul>
[Link]('home',(event) => {
[Link]('Home menu item was clicked');
});
JavaScript 74
Instead of having multiple event handlers, you can assign a single event
handler to handle all the click events:
<ul id="menu">
<li><a id="home">home</a></li>
<li><a id="dashboard">Dashboard</a></li>
<li><a id="report">report</a></li>
</ul>
JavaScript 75
// ES6
let show = () => {
[Link]('Anonymous function');
};
show();
In this example, the anonymous function has no name between the function
keyword and parentheses ().
How about giving a name to IIFE ? it cannot be invoked again after execution.
In essence, an IIFE is a design pattern that allows you to define an anonymous
function, invoke it immediately, and not pollute the global namespace. It's
commonly used in JavaScript to create module-like structures within code.
function() {
// function code here
}
JavaScript 76
2. Enclose the Function Expression in Parentheses/pəˈrenθəsiːz/: The
function is enclosed within an outer set of parentheses. This is done to
distinguish the function as an expression, not a declaration. By
wrapping our anonymous function inside parentheses, we're telling the
JavaScript parser to treat it as an expression.
(function() {
// function code here
})
(function() {
// function code here
})()
(function(a, b) {
[Link](a + b);
})(1, 2) // This will log 3 to the console
(() => {
// function code here
})()
6. Return Values: Just like any other function, an IIFE can return a value
which can be assigned to a variable.
JavaScript 77
let result = (function(a, b) {
return a + b;
})(2, 3) // result will be 5
2. Data privacy: Any variables or functions defined inside the IIFE cannot
be accessed from the outside, providing a level of data privacy.
(function() {
[Link]('IIFE executed!');
})();
// ES6 syntax:
(() => {
[Link]('IIFE executed!');
})();
JavaScript 78
parameters, and other functions within its outer (enclosing) scope even after
the outer function has finished executing.
function outerFunction() {
var outerVariable = 'Hello';
function innerFunction() {
[Link](outerVariable);
}
return innerFunction;
}
Data Privacy: Closures allow you to create private variables and functions
that are inaccessible from outside the scope of the outer function. This
helps in encapsulating/ɪnˈkæpsjuleɪtɪŋ/ data and preventing unwanted
access or modification.
Closure + asynchronous
JavaScript 79
Output:
after 4 second(s):4
after 4 second(s):4
after 4 second(s):4
Why It happened ?
3. When the synchronous tasks are completed, the asynchronous tasks will
be executed(setTimeout)
How to fix it ?
Using the IIFE solution: an IIFE creates a new scope by declaring a function
and immediately execute it.
By using let to declare the index variable, it creates a new block scope for
each iteration of the loop. Each callback function captures its own separate
value of index , which remains unchanged during its execution.
JavaScript 80
for (let index = 1; index <= 3; index++) {
setTimeout(function () {
[Link]('after ' + index + ' second(s):' + ind
}, index * 1000);
}
Currying Function
Currying is a technique in functional programming where a function with
multiple arguments is transformed into a sequence of functions, each taking a
single argument. The curried functions can be called with one argument at a
time, and each call returns a new function that expects the next argument until
all arguments have been provided, and the final result is returned.
Here's an example of a curried function in JavaScript:
function add(x) {
return function(y) {
return x + y;
};
}
// ES6
const add = x => y => x + y;
JavaScript 81
[Link](increment(5)); // Output: 6
The add() function behaves like a function factory. It creates increment() and
addTen() functions with the respective x parameter 1 and 10.
The increment() and addTen() are closures. They share the same function
body but store different scopes.
In this example, the add function takes one argument ( x ) and returns another
function that takes a second argument ( y ). The returned function adds the
values of x and y and returns the result. By calling add with one argument, we
get a partially applied function that we can reuse with different arguments.
let x = 10;
function modifyValue(a) {
a = 20;
[Link](a); // Output: 20
}
modifyValue(x);
[Link](x); // Output: 10
JavaScript 82
In this example, the value of x is copied and assigned to the variable a inside
the modifyValue function. Modifying a does not affect the value of x outside
the function.
JavaScript Advanced Topic - Passing by value of
object(objects)
When objects (including arrays and functions) are assigned to variables or passed
as function arguments, they are passed by reference . This means that instead of
creating a new copy of the object, a reference to the same object in memory is
passed or assigned. Modifying the object through the reference will affect the
original object.
function modifyObject(o) {
[Link] = 20;
[Link]([Link]); // Output: 20
}
modifyObject(obj);
[Link]([Link]); // Output: 20
function, the reference to the object is passed. Modifying the o variable inside
the function also modifies the obj object.
Call() invokes the function and allows you to pass in arguments one by
one.
JavaScript 83
Bind() returns a new function, then you can execute this function by
passing the arguments.
[Link](thisArg, [args]);
JavaScript 84
const person = {
firstName: 'John',
lastName: 'Doe'
};
When you invoke greet('Hi', 'How are you') , the function is called directly
without specifying a context ( this value). In this case, the this value
inside the greet function is undefined , as there is no specific object or
context assigned.
However, when you use apply() to invoke the function with a specific
context ( person ) and pass the arguments as an array, like [Link](person,
['Hi', 'How are you']) , the this value inside the greet function is set to the
person object. The arguments 'Hi' and 'How are you' are passed as
separate elements of the array.
3. bind() : The bind() method is used to create a new function with a bound
this value. It does not immediately invoke the function but returns a new
function with the specified this value permanently bound. It allows you to
curry or preset arguments for the function.
定为传递给 的第一个参数,同时也可以指定绑定函数的一部分参数。这样
bind()
做的目的是为了将函数与特定的对象绑定在一起,以便在后续调用中确保函数中
的 值始终指向指定的对象。
this
的基本用法如下:
bind()
JavaScript 85
const boundFunction = [Link](thisArg, arg
1, arg2, ...);
要绑定的原始函数。
originalFunction :
: 指定绑定函数中的
thisArg 值,即函数执行时的上下文对象。
this
,
arg1 , ...: 可选参数,用于绑定函数的部分参数(也称为偏函数),在
arg2
调用绑定函数时,这些参数会被插入到原始函数的参数之前。
下面是一个使用 的简单示例:
bind()
const person = {
name: 'John',
sayHello: function() {
[Link](`Hello, my name is ${[Link]}.`);
}
};
const otherPerson = {
name: 'Alice'
};
法绑定到 对象上。因此,在调用
otherPerson sayHelloToOtherPerson()时,该函数中
的 值将指向
this 对象,而不是 对象。
otherPerson person
JavaScript 86
方法通常用于创建具有固定上下文的回调函数,避免 值在调用时丢失
bind() this
或指向错误的对象。它在React组件中经常用于事件处理程序,确保事件处理程序
函数中的 值始终指向组件实例。
this
Promise
In JavaScript, a promise is an object that returns a value which you hope to
receive in the future, but not now.
Because the value will be returned by the promise in the future, the promise is
very wellsuited for handling asynchronous operations.
A promise has three states:
• Pending: you don’t know if you will complete learning JavaScript by the next
month.
• Fulfilled: you complete learning JavaScript by the next month.
• Rejected: you don’t learn JavaScript at all
Event Loop
The event loop is a constantly running process that monitors both the callback
queue and the call stack.
When dealing with JavaScript, the runtime uses an event loop to handle
synchronous and asynchronous operations, allowing it to perform non-blocking
I/O operations despite being single-threaded.
For Synchronous Operations: These operations are added to the call stack and
are executed one by one, in the order they were added (this is known as LIFO -
Last In, First Out). Each function waits for the previous function to complete. If
a function is taking too long to run (like a large loop or complex computation), it
can cause the webpage to become unresponsive until that function is done.
This is because the call stack needs to be cleared before anything else (like
user interactions, rendering updates, etc.) can happen.
JavaScript 87
For Asynchronous Operations: Unlike synchronous operations, asynchronous
operations do not block the call stack. When an async operation is initiated
(like making a fetch request, setting a timer, etc.), it's handled off to a web API
provided by the browser. This lets the call stack clear and continue running
other tasks.
The web API manages the operation in the background, separate from the main
JavaScript thread. Once the async operation is complete (like when the fetch
request receives a response, or the timer finishes), the web API adds a
callback function to the task queue.
The event loop constantly checks if the call stack is empty. When the call
stack is clear (meaning all synchronous tasks have completed), the event loop
takes the first task from the task queue and pushes it to the call stack, allowing
the callback function to run.
JavaScript 88
[Link]
If the call stack is not empty, the event loop waits until it is empty and places
the next function from the callback queue to the call stack. If the callback
queue is empty, nothing will happen.
1. Call Stack: The JavaScript runtime maintains a call stack, which is a data
structure that keeps track of the functions being executed. When a function
is called, it is added to the top of the call stack, and when a function
completes, it is removed from the stack.
JavaScript 89
2. Event Queue: In addition to the call stack, there is an event queue that
holds events or tasks to be processed. Events can include user
interactions, network requests, timers, and more.
3. Event Loop: The event loop continuously monitors the call stack and the
event queue. It performs the following steps:
If the call stack is empty, it checks the event queue for pending events.
If there are events in the queue, it takes the first event and pushes its
corresponding callback function onto the call stack for execution.
The function execution begins, and any synchronous code inside the
function is executed.
The event loop repeats this process, checking the call stack and event
queue, and continues to process events as they become available.
By following this cycle, the event loop ensures that JavaScript can handle
asynchronous operations without blocking the main thread, allowing for a
responsive user interface and efficient resource utilization.
It's important to note that callbacks or promises associated with asynchronous
operations are not executed immediately when they are defined. Instead, they
are placed in the event queue and executed by the event loop when the call
stack is empty.
What if you explain the event loop in the sync and async operationally ?
this
In JavaScript, you can use the this keyword in the global and function contexts.
Moreover, the behavior of the this keyword changes between strict and
nonstrict modes.
The this references the object of which the function is a property. In other
words,
the this references the object that is currently calling the function.
JavaScript 90
Global context
In the global context, the this references the global object, which is the
window object on the web browser or global object on [Link].
JavaScript 91