中英文模式阅读
中文模式阅读
英文模式阅读

JavaScript is the most widely used scripting language on earth. Here are some examples of key syntax patterns in JavaScript.
JavaScript是地球上使用最广泛的脚本语言。以下是JavaScript中关键语法模式的一些示例。

Argument Example {#argument-example}

The arguments object is an
参数对象是一个 array-like object
(in that the structure of the object is similar to that of an array; however it should not be considered an array as it has all the functionality of an object) that stores all of the arguments that you passed to a function and is proprietary to that function in particular.
它存储您传递给函数的所有参数,特别是该函数专有的参数。

If you were to pass 3 arguments to a function, say
如果要将3个参数传递给函数,比如说storeNames(), those 3 arguments would be stored inside an object called
,这3个参数将存储在一个名为的对象中 arguments and it would look like this when we pass the arguments
当我们传递参数时它会是这样的storeNames("Mulder", "Scully", "Alex Krycek") to our function:
我们的功能:

  • First, we declare a function and make it return the arguments object.
    首先,我们声明一个函数并使其返回参数对象。

function storeNames() { return arguments; }
function storeNames(){return arguments; }

  • Then, when we execute that function with
    然后,当我们执行该功能时 n arguments , 3 in this case, it will return the object to us and it will
    ,3在这种情况下,它会将对象返回给我们,它会 look like an array. We can convert it to an array, but more on that later...
    数组。我们可以将它转换为数组,但稍后会更多...

// If we execute the following line in the console: storeNames("Mulder", "Scully", "Alex Kryceck"); // The output will be { '0': 'Mulder', '1': 'Scully', '2': 'Alex Kryceck' }
//如果我们在控制台中执行以下行:storeNames("Mulder","Scully","Alex Kryceck"); //输出为{'0':'Mulder','1':'Scully','2':'Alex Kryceck'}

Treat it as an array {#treat-it-as-an-array}

You can invoke arguments by using
您可以使用调用参数arguments[n] (where
(哪里 n is the index of the argument in the array-like object). But if you want to use it as an array for iteration purposes or applying array methods to it, you need to
是类数组对象中参数的索引。但是如果你想将它用作迭代目的的数组或者将数组方法应用于它,你需要 convert it to an array by declaring a variable and using the Array.prototype.slice.call method (because
通过声明一个变量并使用Array.prototype.slice.call方法(因为 arguments is not an array):
不是数组):

var args = Array.prototype.slice.call(arguments);

// or the es6 way:
var args = Array.from(arguments)

Since
以来 slice() has two (the parameter
有两个(参数 end is optional) parameters. You can grab a certain portion of the arguments by specifying the beginning and the ending of your portion (using the
是可选的)参数。您可以通过指定部分的开头和结尾来获取参数的某个部分(使用 slice.call() method renders these two parameters optional, not just
方法将这两个参数呈现为可选,而不仅仅是 end ). Check out the following code:
)。查看以下代码:

function getGrades() {
    var args = Array.prototype.slice.call(arguments, 1, 3);
    return args;
}

// Let's output this!
console.log(getGrades(90, 100, 75, 40, 89, 95));

// OUTPUT SHOULD BE: //
// [100, 75] <- Why? Because it started from index 1 and stopped at index 3
// so, index 3 (40) wasn't taken into consideration.
//
// If we remove the '3' parameter, leaving just (arguments, 1) we'd get
// every argument from index 1: [100, 75, 40, 89, 95].

Optimization issues with Array.slice() {#optimization-issues-with-array-slice-}

There is a little problem: it's not recommended to use slice in the arguments object (optimization reasons)...
有一点问题:不建议在arguments对象中使用slice(优化原因)......

Important : You should not slice on arguments because it prevents optimizations in JavaScript engines (V8 for example). Instead, try constructing a new array by iterating through the arguments object.
:您不应该对参数进行切片,因为它会阻止JavaScript引擎中的优化(例如V8)。相反,尝试通过遍历arguments对象来构造一个新数组。

So, what other method is available to convert
那么,还有哪种方法可以转换 arguments to an array? I recommend the for-loop (not the for-in loop). You can do it like this:
到阵列?我推荐for-loop(不是for-in循环)。你可以这样做:

var args = []; // Empty array, at first.
for (var i = 0; i < arguments.length; i++) {
    args.push(arguments[i])
} // Now 'args' is an array that holds your arguments.

For more information on the optimization issues:
有关优化问题的更多信息:

Optimization Killers: Managing Arguments

ES6 rest parameter as a way to circumvent the arguments object {#es6-rest-parameter-as-a-way-to-circumvent-the-arguments-object}

In ES2015/ES6 it is possible to use the rest parameter (
在ES2015 / ES6中,可以使用rest参数(...) instead of the arguments object in most places. Say we have the following function (non-ES6):
而不是大多数地方的参数对象。假设我们有以下功能(非ES6):

function getIntoAnArgument() {
    var args = arguments.slice();
    args.forEach(function(arg) {
        console.log(arg);
    });
}

That function can be replaced in ES6 by:
该功能可以在ES6中替换为:

function getIntoAnArgument(...args) {
    args.forEach(arg => console.log(arg));
}

Note that we also used an arrow function to shorten the forEach callback!
请注意,我们还使用了箭头函数来缩短forEach回调!

The arguments object is not available inside the body of an arrow function.
arguments对象在箭头函数体内不可用。

The rest parameter must always come as the last argument in your function definition.
rest参数必须始终作为函数定义中的最后一个参数。

function getIntoAnArgument(arg1, arg2, arg3, ...restOfArgs /*no more arguments allowed here*/) { //function body }

Arithmetic Operation Example {#arithmetic-operation-example}

JavaScript provides the user with five arithmetic operators:
JavaScript为用户提供了五个算术运算符:+,
-,
*,
/ and
%. The operators are for addition, subtraction, multiplication, division and remainder, respectively.
。运算符分别用于加法,减法,乘法,除法和余数。

Addition {#addition}

Syntax

a + b

Usage

2 + 3          // returns 5
true + 2       // interprets true as 1 and returns 3
false + 5      // interprets false as 0 and returns 5
true + "bar"   // concatenates the boolean value and returns "truebar"
5 + "foo"      // concatenates the string and the number and returns "5foo"
"foo" + "bar"  // concatenates the strings and returns "foobar"

Hint: There is a handy [increment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment_() operator that is a great shortcut when you're adding numbers by 1.
有一个方便的[增量](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment_()运算符,当你添加数字时,这是一个很好的快捷方式1。

Subtraction {#subtraction}

Syntax

a - b

Usage

2 - 3      // returns -1
3 - 2      // returns 1
false - 5  // interprets false as 0 and returns -5
true + 3   // interprets true as 1 and returns 4
5 + "foo"  // returns NaN (Not a Number)

Hint: There is a handy [decrement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement_(--) operator that is a great shortcut when you're subtracting numbers by 1.
有一个方便的[减量](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement_( - )运算符,这是一个很好的快捷方式,当你减去数字乘以1。

Multiplication {#multiplication}

Syntax

a * b

Usage

2 * 3                // returns 6
3 * -2               // returns -6
false * 5            // interprets false as 0 and returns 0
true * 3             // interprets true as 1 and returns 3
5 * "foo"            // returns NaN (Not a Number)
Infinity * 0         // returns NaN
Infinity * Infinity  // returns Infinity

Division {#division}

Syntax

a / b

Usage

3 / 2                // returns 1.5
3.0 / 2/0            // returns 1.5
3 / 0                // returns Infinity
3.0 / 0.0            // returns Infinity
-3 / 0               // returns -Infinity
false / 5            // interprets false as 0 and returns 0
true / 2             // interprets true a 1 and returns 0.5
5 + "foo"            // returns NaN (Not a Number)
Infinity / Infinity  // returns NaN

Remainder {#remainder}

Syntax

a % b

Usage

3 % 2          // returns 1
true % 5       // interprets true as 1 and returns 1
false % 4      // interprets false as 0 and returns 0
3 % "bar"      // returns NaN

Increment {#increment}

Syntax

a++ or ++a

Usage
// Postfix x = 3; // declare a variable y = x++; // y = 4, x = 3
//后缀x = 3; //声明变量y = x ++; // y = 4,x = 3
// Prefix var a = 2; b = ++a; // a = 3, b = 3
//前缀var a = 2; b = ++ a; // a = 3,b = 3

Decrement {#decrement}

Syntax

a-- or --a

Usage
// Postfix x = 3; // declare a variable y = x---; // y = 3, x = 3
//后缀x = 3; //声明变量y = x ---; // y = 3,x = 3
// Prefix var a = 2; b = ---a; // a = 1, b = 1
//前缀var a = 2; b = --- a; // a = 1,b = 1 !Important! As you can see, you
如你所见,你 cannot perform any sort of operations on
执行任何类型的操作Infinity.

Arrow Function Example {#arrow-function-example}

Arrow functions are a new ES6 syntax for writing JavaScript function expressions. The shorter syntax saves time, as well as simplifying the function scope.
Arrow函数是用于编写JavaScript函数表达式的新ES6语法。较短的语法节省了时间,并简化了功能范围。

What are arrow functions? {#what-are-arrow-functions}

An arrow function expression is a more concise syntax for writing function expressions using a "fat arrow" token (
箭头函数表达式是使用"胖箭头"令牌编写函数表达式的更简洁的语法(=>).
)。

The basic syntax {#the-basic-syntax}

Below is a basic example of an arrow function:
以下是箭头功能的基本示例:

// ES5 syntax
var multiply = function(x, y) {
  return x * y;
};

// ES6 arrow function
var multiply = (x, y) => { return x * y; };

// Or even simpler
var multiply = (x, y) => x * y;    

You no longer need the
你不再需要了function and
return keywords, or even the curly brackets.
关键字,甚至是大括号。

A simplified this {#a-simplified-this}

Before arrow functions, new functions defined their own
在箭头功能之前,新功能定义了自己的功能this value. To use
值。使用this inside a traditional function expression, we have to write a workaround like so:
在传统的函数表达式中,我们必须编写一个像这样的解决方法:

// ES5 syntax
function Person() {
  // we assign `this` to `self` so we can use it later
  var self = this;
  self.age = 0;

  setInterval(function growUp() {
    // `self` refers to the expected object
    self.age++;
  }, 1000);
}

An arrow function doesn't define its own
箭头函数没有定义自己的this value, it inherits
价值,它继承this from the enclosing function:
从封闭功能:

// ES6 syntax
function Person(){
  this.age = 0;

  setInterval(() => {
    // `this` now refers to the Person object, brilliant!
    this.age++;
  }, 1000);
}

var p = new Person();

Assignment Operators {#assignment-operators}

Assignment Operator Example {#assignment-operator-example}

Assignment operators, as the name suggests, assign (or re-assign) values to a variable. While there are quite a few variations on the assignment operators, they all build off of the basic assignment operator.
赋值运算符,顾名思义,为变量赋值(或重新赋值)。虽然赋值运算符有很多变体,但它们都是基本赋值运算符的构建。

Syntax =
语法= y;DescriptionNecessityxVariableRequired=Assignment operatorRequiredyValue to assign to variableRequired

Examples {#examples}

let initialVar = 5;   // Variable initialization requires the use of an assignment operator

let newVar = 5;
newVar = 6;   // Variable values can be modified using an assignment operator

Variations {#variations}

The other assignment operators are a shorthand for performing some operation using the variable (indicated by x above) and value (indicated by y above) and then assigning the result to the variable itself.
其他赋值运算符是使用变量(由上面的x表示)和值(由上面的y表示)执行某些操作的简写,然后将结果赋给变量本身。

For example, below is the syntax for the addition assignment operator:
例如,下面是加法赋值运算符的语法:

x += y;

This is the same as applying the addition operator and reassigning the sum to the original variable (that is, x), which can be expressed by the following code:
这与应用加法运算符并将总和重新分配给原始变量(即x)相同,可以通过以下代码表示:

x = x + y;

To illustrate this using actual values, here is another example of using the addition assignment operator:
为了使用实际值来说明这一点,下面是使用加法赋值运算符的另一个示例:

let myVar = 5;   // value of myVar: 5
myVar += 7;   // value of myVar: 12 = 5 + 7

Boolean Example {#boolean-example}

Booleans are a primitive datatype commonly used in computer programming languages. By definition, a boolean has two possible values:
布尔值是计算机编程语言中常用的原始数据类型。根据定义,布尔值有两个可能的值:true or
要么false.

In Javascript, there is often implicit type coercion to boolean. If for example you have an if statement which checks a certain expression, that expression will be coerced to a boolean:
在Javascript中,通常存在对boolean的隐式类型强制。例如,如果您有一个if语句来检查某个表达式,那么该表达式将被强制转换为布尔值:

var a = 'a string';
if (a) {
  console.log(a); // logs 'a string'
}

There are only a few values that will be coerced to false:
只有少数值会被强制转换为false:

  • false (not really coerced, as it already is false)
  • null
  • undefined
  • NaN
  • 0
  • " (empty string)

All other values will be coerced to true. When a value is coerced to a boolean, we also call that either 'falsy' or 'truthy'.
所有其他值将被强制转换为true。当一个值被强制转换为布尔值时,我们也称之为&#39;falsy&#39;或&#39;truthy&#39;。

One way that type coercion is used is with the use of the or (
使用类型强制的一种方法是使用或(||) and and (
)和(和&&) operators:
)运营商:

var a = 'word';
var b = false;
var c = true;
var d = 0
var e = 1
var f = 2
var g = null

console.log(a || b); // 'word'
console.log(c || a); // true
console.log(b || a); // 'word'
console.log(e || f); // 1
console.log(f || e); // 2
console.log(d || g); // null
console.log(g || d); // 0
console.log(a && c); // true
console.log(c && a); // 'word'

As you can see, the
如你所见, or operator checks the first operand. If this is true or truthy, it returns it immediately (which is why we get 'word' in the first case & true in the second case). If it is not true or truthy, it returns the second operand (which is why we get 'word' in the third case).
运算符检查第一个操作数。如果这是真的或真实的,它会立即返回它(这就是为什么我们在第一种情况下得到&#39;word&#39;而在第二种情况下得到true)。如果它不是真或真,它会返回第二个操作数(这就是我们在第三种情况下获得&#39;word&#39;的原因)。

With the and operator it works in a similar way, but for 'and' to be true, both operands need to be truthy. So it will always return the second operand if both are true/truthy, otherwise it will return false. That is why in the fourth case we get true and in the last case we get 'word'.
使用和运算符它以类似的方式工作,但为了&#39;和&#39;为真,两个操作数都需要真实。因此,如果两者都是真/真,它将始终返回第二个操作数,否则它将返回false。这就是为什么在第四种情况下我们得到了真实,在最后一种情况下我们得到了&#39;字&#39;。

The Boolean Object {#the-boolean-object}

There is also a native JavaScript object that wraps around a value. The value passed as the first parameter is converted to a boolean value, if necessary. If the value is omitted, 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object or the string "false", create an object with an initial value of true.
还有一个包装值的本机JavaScript对象。如有必要,作为第一个参数传递的值将转换为布尔值。如果省略该值,0,-0,null,false,NaN,undefined或空字符串(""),则该对象的初始值为false。所有其他值(包括任何对象或字符串"false")都会创建一个初始值为true的对象。

Do not confuse the primitive Boolean values true and false with the true and false values of the Boolean object.
不要将原始布尔值true和false与Boolean对象的true和false值混淆。

More Details {#more-details}

Any object whose value is not undefined or null, including a Boolean object whose value is false, evaluates to true when passed to a conditional statement. If true, this will execute the function. For example, the condition in the following if statement evaluates to true:
任何值未定义或为null的对象(包括值为false的Boolean对象)在传递给条件语句时计算结果为true。如果为true,则执行该函数。例如,以下if语句中的条件求值为true:

var x = new Boolean(false);
if (x) {
  // this code is executed
}

This behavior does not apply to Boolean primitives. For example, the condition in the following if statement evaluates to false:
此行为不适用于布尔基元。例如,以下if语句中的条件求值为false:

var x = false;
if (x) {
  // this code is not executed
}

Do not use a Boolean object to convert a non-boolean value to a boolean value. Instead, use Boolean as a function to perform this task:
不要使用Boolean对象将非布尔值转换为布尔值。而是使用布尔值作为函数来执行此任务:

var x = Boolean(expression);     // preferred
var x = new Boolean(expression); // don't use

If you specify any object, including a Boolean object whose value is false, as the initial value of a Boolean object, the new Boolean object has a value of true.
如果指定任何对象(包括值为false的Boolean对象)作为Boolean对象的初始值,则新的Boolean对象的值为true。

var myFalse = new Boolean(false);   // initial value of false
var g = new Boolean(myFalse);       // initial value of true
var myString = new String('Hello'); // string object
var s = new Boolean(myString);      // initial value of true

Do not use a Boolean object in place of a Boolean primitive.
不要使用布尔对象代替布尔基元。

Callback Functions {#callback-functions}

This section gives a brief introduction to the concept and usage of callback functions in Javascript.
本节简要介绍了Javascript中回调函数的概念和用法。

Functions are Objects {#functions-are-objects}

The first thing we need to know is that in Javascript, functions are first-class objects. As such, we can work with them in the same way we work with other objects, like assigning them to variables and passing them as arguments into other functions. This is important, because it's the latter technique that allows us to extend functionality in our applications.
我们需要知道的第一件事是在Javascript中,函数是一流的对象。因此,我们可以像处理其他对象一样使用它们,比如将它们分配给变量并将它们作为参数传递给其他函数。这很重要,因为后一种技术允许我们在应用程序中扩展功能。

Callback Function Example {#callback-function-example}

A
一种 callback function is a function that is passed
是一个传递的函数 as an argument to another function, to be "called back" at a later time.
到另一个功能,以后再"回叫"。

A function that accepts other functions as arguments is called a
接受其他函数作为参数的函数称为a higher-order function , which contains the logic for
,其中包含的逻辑 when the callback function gets executed. It's the combination of these two that allow us to extend our functionality.
回调函数被执行。这两者的结合使我们能够扩展我们的功能。

To illustrate callbacks, let's start with a simple example:
为了说明回调,让我们从一个简单的例子开始:

function createQuote(quote, callback){ 
  var myQuote = "Like I always say, " + quote;
  callback(myQuote); // 2
}

function logQuote(quote){
  console.log(quote);
}

createQuote("eat your vegetables!", logQuote); // 1

// Result in console: 
// Like I always say, eat your vegetables!

In the above example,
在上面的例子中,createQuote is the higher-order function, which accepts two arguments, the second one being the callback. The
是高阶函数,它接受两个参数,第二个是回调。该logQuote function is being used to pass in as our callback function. When we execute the
函数被用来传入我们的回调函数。当我们执行createQuote function
功能 (1) , notice that we are
,请注意我们是 not appending parentheses to
括号到logQuote when we pass it in as an argument. This is because we do not want to execute our callback function right away, we simply want to pass the function definition along to the higher-order function so that it can be executed later.
当我们作为一个参数传递它。这是因为我们不想立即执行我们的回调函数,我们只是想将函数定义传递给高阶函数,以便以后执行。

Also, we need to ensure that if the callback function we pass in expects arguments, we supply those arguments when executing the callback
此外,我们需要确保如果我们传入的回调函数需要参数,我们在执行回调时提供这些参数 (2) . In the above example, that would be the
。在上面的例子中,那将是callback(myQuote);statement, since we know that
声明,因为我们知道logQuote expects a quote to be passed in.
期望报价传递。

Additionally, we can pass in anonymous functions as callbacks. The below call to
此外,我们可以传递匿名函数作为回调。下面打电话给createQuote would have the same result as the above example:
将与上面的示例具有相同的结果:

createQuote("eat your vegetables!", function(quote){ 
  console.log(quote); 
});

Incidentally, you don't
顺便说一下,你没有 have to use the word "callback" as the name of your argument. Javascript just needs to know that it's the correct argument name. Based on the above example, the below function will behave in exactly the same manner.
使用"回调"这个词作为你的论点的名称。 Javascript只需要知道它是正确的参数名称。基于上面的例子,下面的函数将以完全相同的方式运行。

function createQuote(quote, functionToCall) { 
  var myQuote = "Like I always say, " + quote;
  functionToCall(myQuote);
}

Why use Callbacks? {#why-use-callbacks}

Most of the time we are creating programs and applications that operate in a
大多数时候,我们正在创建以a。中运行的程序和应用程序 synchronous manner. In other words, some of our operations are started only after the preceding ones have completed.
方式。换句话说,我们的一些操作只有在前面的操作完成后才会启动。

Often when we request data from other sources, such as an external API, we don't always know
通常,当我们从其他来源请求数据时,例如外部API,我们并不总是知道 when our data will be served back. In these instances we want to wait for the response, but we don't always want our entire application grinding to a halt while our data is being fetched. These situations are where callback functions come in handy.
我们的数据将被送回。在这些情况下,我们希望等待响应,但我们并不总是希望在获取数据时我们的整个应用程序停止运行。这些情况是回调函数派上用场的地方。

Let's take a look at an example that simulates a request to a server:
我们来看一个模拟对服务器的请求的示例:

function serverRequest(query, callback){
  setTimeout(function(){
    var response = query + "full!";
    callback(response);
  },5000);
}

function getResults(results){
  console.log("Response from the server: " + results);
}

serverRequest("The glass is half ", getResults);

// Result in console after 5 second delay:
// Response from the server: The glass is half full!

In the above example, we make a mock request to a server. After 5 seconds elapse, the response is modified and then our callback function
在上面的示例中,我们向服务器发出模拟请求。经过5秒后,响应被修改,然后是我们的回调函数getResults gets executed. To see this in action, you can copy/paste the above code into your browser's developer tool and execute it.
被执行。要查看此操作,您可以将上述代码复制/粘贴到浏览器的开发人员工具中并执行它。

Also, if you are already familiar with
另外,如果你已经熟悉了setTimeout, then you've been using callback functions all along. The anonymous function argument passed into the above example's
那么你一直在使用回调函数。匿名函数参数传递给上面的例子setTimeout function call is also a callback! So the example's original callback is actually executed by another callback. Be careful not to nest too many callbacks if you can help it, as this can lead to something called "callback hell"! As the name implies, it isn't a joy to deal with.
函数调用也是回调!因此,示例的原始回调实际上是由另一个回调执行的。如果你可以提供帮助,小心不要嵌套太多的回调,因为这会导致一种叫做"回调地狱"的东西!顾名思义,处理起来并不是一种乐趣。

JavaScript Class Example {#javascript-class-example}

JavaScript does not have the concept of classes inherently.
JavaScript本身并没有类的概念。

But we could simulate the functionalities of a class by taking advantage of the prototypal nature of JavaScript.
但是我们可以通过利用JavaScript的原型性质来模拟类的功能。

This section assumes that you have a basic understanding of
本节假定您已基本了解prototypes.

For the sake of clarity, let us assume that we want to create a class which can do the following
为了清楚起见,让我们假设我们想要创建一个可以执行以下操作的类

var p = new Person('James','Bond'); // create a new instance of Person class
	p.log() // Output: 'I am James Bond' // Accessing a function in the class
	// Using setters and getters 
	p.profession = 'spy'
	p.profession // output: James bond is a spy

Using class keyword {#using-class-keyword}

Like in any other programming language, you can now use the
与任何其他编程语言一样,您现在可以使用class keyword to create a class.
用于创建类的关键字。

This is not supported in older browsers and was introduced in ECMAScript 2015.
旧版浏览器不支持此功能,并且已在ECMAScript 2015中引入。

class is just a syntactic sugar over JavaScript's existing prototype-based inheritance model.
只是JavaScript现有的基于原型的继承模型的语法糖。

In general, programmers use the following ways to create a class in JavaScript.
通常,程序员使用以下方法在JavaScript中创建类。

Using methods added to prototypes: {#using-methods-added-to-prototypes-}

Here, all the methods are added to prototype
在这里,所有方法都被添加到原型中

function Person(firstName, lastName) {
    this._firstName = firstName;
    this._lastName = lastName;
}

Person.prototype.log = function() {
    console.log('I am', this._firstName, this._lastName);
}

// This line adds getters and setters for the profession object. Note that in general you could just write your own get and set functions like the 'log' method above.
// Since in this example we are trying the mimic the class above, we try to use the getters and setters property provided by JavaScript
Object.defineProperty(Person.prototype, 'profession', {
    set: function(val) {
        this._profession = val;
    },
    get: function() {
        console.log(this._firstName, this._lastName, 'is a', this._profession);
    }
})

You could also write prototype methods over function
您还可以在函数上编写原型方法Person as below:
如下:

Person.prototype = {
    log: function() {
        console.log('I am ', this._firstName, this._lastName);
    }
    set profession(val) {
        this._profession = val;
    }

    get profession() {
        console.log(this._firstName, this._lastName, 'is a', this._profession);
    }

}

Using methods added internally {#using-methods-added-internally}

Here the methods are added internally instead of prototype:
这里的方法是在内部添加而不是原型:

function Person(firstName, lastName) {
    this._firstName = firstName;
    this._lastName = lastName;

    this.log = function() {
        console.log('I am ', this._firstName, this._lastName);
    }

    Object.defineProperty(this, 'profession', {
        set: function(val) {
            this._profession = val;
        },
        get: function() {
            console.log(this._firstName, this._lastName, 'is a', this._profession);
        }
    })
}

Hiding details in classes with symbols {#hiding-details-in-classes-with-symbols}

Most often, some properties and methods have to be hidden to prevent access from outside the function.
通常,必须隐藏一些属性和方法以防止从函数外部进行访问。

With classes, to obtain this functionality, one way to do this is by using symbols. Symbol is a new built-in type of JavaScript, which can be invoked to give a new symbol value. Every Symbol is unique and can be used as a key on object.
对于类,要获得此功能,一种方法是使用符号。 Symbol是一种新的内置JavaScript类型,可以调用它来提供新的符号值。每个符号都是唯一的,可以用作对象的键。

So one use case of symbols is that you can add something to an object you might not own, and you might not want to collide with any other keys of object. Therefore, creating a new one and adding it as a property to that object using symbol is the safest. Also, when symbol value is added to an object, no one else will know how to get it.
因此,符号的一个用例是,您可以向可能不拥有的对象添加内容,并且您可能不希望与对象的任何其他键冲突。因此,创建一个新的并使用符号将其作为属性添加到该对象是最安全的。此外,当符号值添加到对象时,没有其他人知道如何获取它。

class Person {
    constructor(firstName, lastName) {
        this._firstName = firstName;
        this._lastName = lastName;
    }

    log() {
        console.log('I am', this._firstName, this._lastName);
    }

    // setters
    set profession(val) {
        this._profession = val;
    }
    // getters
    get profession() {
        console.log(this._firstName, this._lastName, 'is a', this._profession);
    }
// With the above code, even though we can access the properties outside the function to change their content what if we don't want that.
// Symbols come to rescue.
let s_firstname  = new Symbol();

class Person {
    constructor(firstName, lastName) {
        this[s_firstName] = firstName;
        this._lastName = lastName;
    }

    log() {
        console.log('I am', this._firstName, this._lastName);
    }

    // setters
    set profession(val) {
        this._profession = val;
    }
    // getters
    get profession() {
        console.log(this[s_firstName], this._lastName, 'is a', this._profession);
    }

JavaScript Closure Example {#javascript-closure-example}

A closure is the combination of a function and the lexical environment (scope) within which that function was declared. Closures are a fundamental and powerful property of Javascript. This section discusses the 'how' and 'why' about Closures:
闭包是函数和声明该函数的词法环境(范围)的组合。闭包是Javascript的基础和强大属性。本节讨论关于闭包的&#39;方式&#39;和&#39;原因&#39;:

Example {#example}

//we have an outer function named walk and an inner function named fly

function walk (){
  
  var dist = '1780 feet';
  
  function fly(){
    console.log('At '+dist);
  }
  
  return fly;
}

var flyFunc = walk(); //calling walk returns the fly function which is being assigned to flyFunc
//you would expect that once the walk function above is run
//you would think that JavaScript has gotten rid of the 'dist' var

flyFunc(); //Logs out 'At 1780 feet'
//but you still can use the function as above 
//this is the power of closures

Another Example {#another-example}

function by(propName) {
    return function(a, b) {
        return a[propName] - b[propName];
    }
}

const person1 = {name: 'joe', height: 72};
const person2 = {name: 'rob', height: 70};
const person3 = {name: 'nicholas', height: 66};

const arr_ = [person1, person2, person3];

const arr_sorted = arr_.sort(by('height')); // [ { name: 'nicholas', height: 66 }, { name: 'rob', height: 70 },{ name: 'joe', height: 72 } ]

The closure 'remembers' the environment in which it was created. This environment consists of any local variables that were in-scope at the time the closure was created.
闭包&#39;记住&#39;创建它的环境。此环境由创建闭包时在范围内的任何局部变量组成。

function outside(num) {
  var rememberedVar = num; // In this example, rememberedVar is the lexical environment that the closure 'remembers'
  return function inside() { // This is the function which the closure 'remembers'
    console.log(rememberedVar)
  }
}

var remember1 = outside(7); // remember1 is now a closure which contains rememberedVar = 7 in its lexical environment, and //the function 'inside'
var remember2 = outside(9); // remember2 is now a closure which contains rememberedVar = 9 in its lexical environment, and //the function 'inside'

remember1(); // This now executes the function 'inside' which console.logs(rememberedVar) => 7
remember2(); // This now executes the function 'inside' which console.logs(rememberedVar) => 9 

Closures are useful because they let you 'remember' data and then let you operate on that data through returned functions. This allows Javascript to emulate private methods that are found in other programming languages. Private methods are useful for restricting access to code as well as managing your global namespace.
闭包很有用,因为它们让您"记住"数据,然后让您通过返回的函数操作该数据。这允许Javascript模拟其他编程语言中的私有方法。私有方法对于限制对代码的访问以及管理全局命名空间非常有用。

Private variables and methods {#private-variables-and-methods}

Closures can also be used to encapsulate private data/methods. Take a look at this example:
闭包还可用于封装私有数据/方法。看看这个例子:

const bankAccount = (initialBalance) => {
  const balance = initialBalance;

  return {
    getBalance: function() {
      return balance;
    },
    deposit: function(amount) {
      balance += amount;
      return balance;
    },
  };
};

const account = bankAccount(100);

account.getBalance(); // 100
account.deposit(10); // 110

In this example, we won't be able to access
在此示例中,我们将无法访问balance from anywhere outside of the
从外面的任何地方bankAccount function, which means we've just created a private variable.
函数,这意味着我们刚刚创建了一个私有变量。

Where's the closure? Well, think about what
封闭在哪里?那么,想想什么bankAccount() is returning. It actually returns an Object with a bunch of functions inside it, and yet when we call
正在回归它实际上返回一个带有一堆函数的Object,但是当我们调用它时account.getBalance(), the function is able to "remember" its initial reference to
,该函数能够"记住"其初始引用balance.

That is the power of the closure, where a function "remembers" its lexical scope (compile time scope), even when the function is executed outside that lexical scope.
这就是闭包的强大功能,即函数"记住"它的词法范围(编译时范围),即使函数在词法范围之外执行也是如此。

Emulating block-scoped variables {#emulating-block-scoped-variables}

Javascript did not have a concept of block-scoped variables. Meaning that when defining a variable inside a for-loop, for example, this variable was visible from outside the for-loop as well. So how can closures help us solve this problem? Let's take a look.
Javascript没有块范围变量的概念。例如,在for循环中定义变量时,这个变量也可以从for循环外部看到。那么闭包如何帮助我们解决这个问题呢?让我们来看看。

    var funcs = [];
    
    for(var i = 0; i < 3; i++){
        funcs[i] = function(){
            console.log('My value is ' + i);  //creating three different functions with different param values.
        }
    }
    
    for(var j = 0; j < 3; j++){
        funcs[j]();             // My value is 3
                                // My value is 3
                                // My value is 3
    }

Since the variable i does not have block-scope, it's value within all three functions was updated with the loop counter and created malicious values. Closures can help us solve this issue by creating a snapshot of the environment the function was in when it was created, preserving its state.
由于变量i没有块范围,因此使用循环计数器更新了所有三个函数中的值,并创建了恶意值。闭包可以通过创建函数创建时环境的快照来帮助我们解决此问题,从而保留其状态。

    var funcs = [];
    
    var createFunction = function(val){
	    return function() {console.log("My value: " + val);};
    }

    for (var i = 0; i < 3; i++) {
        funcs[i] = createFunction(i);
    }
    for (var j = 0; j < 3; j++) {
        funcs[j]();                 // My value is 0
                                    // My value is 1
                                    // My value is 2
    }

The later versions of Javascript (ES6+) have a new keyword called let which can be used to give the variable a blockscope. There are also many functions (forEach) and entire libraries (lodash.js) that are dedicated to solving such problems as the ones explained above. They can certainly boost your productivity, however it remains extremely important to have knowledge of all these issues when attempting to create something big.
更高版本的Javascript(ES6 +)有一个名为let的新关键字,可用于为变量提供一个blockscope。还有许多函数(forEach)和整个库(lodash.js)致力于解决上述问题。它们当然可以提高您的工作效率,但是在尝试创建大型项目时了解所有这些问题仍然非常重要。

Closures have many special applications that are useful when creating large Javascript programs.
闭包有很多特殊的应用程序,在创建大型Javascript程序时很有用。

  1. Emulating private variables or encapsulation
  2. Making Asynchronous server side calls
  3. Creating a block-scoped variable.

Emulating private variables {#emulating-private-variables}

Unlike many other languages, Javascript does not have a mechanism which allows you to create encapsulated instance variables within an object. Having public instance variables can cause a lot of problems when building medium to large programs. However with closures, this problem can be mitigated.
与许多其他语言不同,Javascript没有一种机制允许您在对象中创建封装的实例变量。在构建中型到大型程序时,使用公共实例变量会导致很多问题。但是对于闭包,可以减轻这个问题。

Much like in the previous example, you can build functions which return object literals with methods that have access to the object's local variables without exposing them. Thus, making them effectively private.
与前面的示例非常相似,您可以使用可以访问对象的局部变量的方法构建返回对象文字的函数,而不会暴露它们。因此,使它们实际上是私密的。

Closures can also help you manage your global namespace to avoid collisions with globally shared data. Usually, all global variables are shared between all scripts in your project, which will definitely give you a lot of trouble when building medium to large programs.
闭包还可以帮助您管理全局命名空间,以避免与全局共享数据冲突。通常,所有全局变量都在项目中的所有脚本之间共享,这在构建中型到大型程序时肯定会给您带来很多麻烦。

That is why library and module authors use closures to hide an entire module's methods and data. This is called the module pattern, it uses an immediately invoked function expression which exports only certain functionality to the outside world, significantly reducing the amount of global references.
这就是为什么库和模块作者使用闭包来隐藏整个模块的方法和数据的原因。这称为模块模式,它使用立即调用的函数表达式,该函数表达式仅将某些功能导出到外部世界,从而显着减少了全局引用的数量。

Here's a short sample of a module skeleton.
这是模块骨架的简短示例。

var myModule = (function() = {
    let privateVariable = 'I am a private variable';
    
    let method1 = function(){ console.log('I am method 1'); };
    let method2 = function(){ console.log('I am method 2, ', privateVariable); };
    
    return {
        method1: method1,
        method2: method2
    }
}());

myModule.method1(); // I am method 1
myModule.method2(); // I am method 2, I am a private variable

Closures are useful for capturing new instances of private variables contained in the 'remembered' environment, and those variables can only be accessed through the returned function or methods.
闭包对于捕获"记住的"环境中包含的私有变量的新实例很有用,并且这些变量只能通过返回的函数或方法来访问。

Programmers use comments to add hints, notes, suggestions, or warnings to their source code; they have no effect on the actual output of the code. Comments can be very helpful in explaining the intent of what your code is or should be doing.
程序员使用注释向其源代码添加提示,注释,建议或警告;它们对代码的实际输出没有影响。注释可以非常有助于解释您的代码应该或应该做什么的意图。

It is always best practice when starting out to comment more often than not, as it can help those reading your code to understand what exactly your code is intending to do.
在开始经常评论时,这总是最好的做法,因为它可以帮助那些阅读代码的人了解您的代码究竟打算做什么。

JavaScript has two ways of assigning comments in its code.
JavaScript有两种在代码中分配注释的方法。

The first way is the
第一种方式是// comment; all text following
评论;所有文字如下// on the same line into a comment. For example:
在同一行发表评论。例如:

function hello() {
  // This is a one line JavaScript comment
  console.log("Hello world!");
}
hello();

The second way is the
第二种方式是/* */ comment, which can be used for both single-line and multi-line comments. For example:
注释,可用于单行和多行注释。例如:

function hello() {
  /* This is a one line JavaScript comment */
  console.log("Hello world!");
}
hello();

function hello() {
  /* This comment spans multiple lines. Notice
     that we don't need to end the comment until we're done. */
  console.log("Hello world!");
}
hello();

You can also prevent execution of Javascript code just commeting the code lines like this:
你也可以阻止执行Javascript代码,只需要像下面这样代码行:

function hello() {
  /*console.log("Hello world!");*/
}
hello();

More Information: {#more-information-}

How To Write Comments in JavaScript

  1. Highlight text to be commented
  2. Mac: Push Command(Apple Key) & "/"
  3. Windows: Push Control & "/"
  4. You can also uncomment code by doing the same steps

A shortcut to comment out a section of Javascript in many code editors is to highlight the lines of code you want to comment out, then press `Cmd/Ctrl + /`.
在许多代码编辑器中注释掉Javascript部分的快捷方式是突出显示要注释掉的代码行,然后按`Cmd / Ctrl + /`。

Comments are also very helpful for code testing as you can prevent a certain code-line/block from running:
注释对代码测试也非常有用,因为您可以阻止某个代码行/块运行:

function hello() {
  // The statement below is not going to get executed
  // console.log('hi')
  }
hello();

function hello() {
  // The statements below are not going to get executed
  /*
  console.log('hi');
  console.log('code-test');
  */
}
hello();

JavaScript Comparison Operator Example {#javascript-comparison-operator-example}

JavaScript has both
JavaScript都有 strict and
type--converting comparisons.
比较。

  • A strict comparison (e.g. ===) is only true if the operands are of the same type.
  • The more commonly used abstract comparison (e.g. ==) converts the operands to the same Type before making the comparison.
  • For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.
  • Strings are compared based on standard lexicographical ordering, using Unicode values.

Features of comparisons: {#features-of-comparisons-}

  • Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding positions.
  • Two numbers are strictly equal when they are numerically equal (have the same number value). NaN is not equal to anything, including NaN. Positive and negative zeros are equal to one another.
  • Two Boolean operands are strictly equal if both are true or both are false.
  • Two distinct objects are never equal for either strict or abstract comparisons.
  • An expression comparing Objects is only true if the operands reference the same Object.
  • Null and Undefined Types are strictly equal to themselves and abstractly equal to each other.

Equality operators {#equality-operators}

Equality (==) {#equality-}

The equality operator converts the operands if they are
如果是,则等于运算符转换操作数 not of the same type , then applies strict comparison. If
,然后应用严格的比较。如果 both operands are objects , then JavaScript compares internal references which are equal when operands refer to the same object in memory.
,然后JavaScript比较当操作数引用内存中的同一对象时相等的内部引用。

Syntax {#syntax}

 x == y

Examples {#examples-1}

 1   ==  1        // true
"1"  ==  1        // true
 1   == '1'       // true
 0   == false     // true
 0   == null      // false

   0   == undefined   // false
 null  == undefined   // true

Inequality (!=) {#inequality-}

The inequality operator returns true if the operands are not equal. If the two operands are
如果操作数不相等,则不等运算符返回true。如果两个操作数是 not of the same type , JavaScript attempts to convert the operands to an appropriate type for the comparison. If
,JavaScript尝试将操作数转换为适当的类型进行比较。如果 both operands are objects , then JavaScript compares internal references which are not equal when operands refer to different objects in memory.
,然后JavaScript比较当操作数引用内存中的不同对象时不相等的内部引用。

Syntax {#syntax-1}

x != y

Examples {#examples-2}

1 !=   2     // true
1 !=  "1"    // false
1 !=  '1'    // false
1 !=  true   // false
0 !=  false  // false

Identity / strict equality (===) {#identity-strict-equality-}

The identity operator returns true if the operands are strictly equal
如果操作数严格相等,则identity运算符返回true with no type conversion .

Syntax {#syntax-2}

x === y

Examples {#examples-3}

3 === 3   // true
3 === '3' // false

Non-identity / strict inequality (!==) {#non-identity-strict-inequality-}

The non-identity operator returns true if the operands
如果操作数,则非标识运算符返回true are not equal and/or not of the same type .

Syntax {#syntax-3}

x !== y

Examples {#examples-4}

3 !== '3' // true
4 !== 3   // true

Relational operators {#relational-operators}

Greater than operator (>) {#greater-than-operator-}

The greater than operator returns true if the left operand is greater than the right operand.
如果左操作数大于右操作数,则大于运算符返回true。

Syntax {#syntax-4}

x > y

Examples {#examples-5}

4 > 3 // true

Greater than or equal operator (>=) {#greater-than-or-equal-operator-}

The greater than or equal operator returns true if the left operand is greater than or equal to the right operand.
如果左操作数大于或等于右操作数,则大于或等于运算符返回true。

Syntax {#syntax-5}

x >= y

Examples {#examples-6}

4 >= 3 // true
3 >= 3 // true

Less than operator (<) {#less-than-operator-}

The less than operator returns true if the left operand is less than the right operand.
如果左操作数小于右操作数,则小于运算符返回true。

Syntax {#syntax-6}

x < y

Examples {#examples-7}

3 < 4 // true

Less than or equal operator (<=) {#less-than-or-equal-operator-}

The less than or equal operator returns true if the left operand is less than or equal to the right operand.
如果左操作数小于或等于右操作数,则小于或等于运算符返回true。

Syntax {#syntax-7}

x <= y

Examples {#examples-8}

3 <= 4 // true

JavaScript Form Validation Example {#javascript-form-validation-example}

Form validation used to occur at the server, after the client had entered all the necessary data and then pressed the Submit button. If the data entered by a client was incorrect or was simply missing, the server would have to send all the data back to the client and request that the form be resubmitted with correct information. This was really a lengthy process which used to put a lot of burden on the server.
在客户端输入所有必要数据然后按下"提交"按钮后,在服务器上进行表单验证。如果客户端输入的数据不正确或者丢失了,则服务器必须将所有数据发送回客户端,并请求使用正确的信息重新提交表单。这真是一个漫长的过程,过去常常给服务器带来很多负担。

JavaScript provides a way to validate form's data on the client's computer before sending it to the web server. Form validation generally performs two functions:
JavaScript提供了一种在将表单数据发送到Web服务器之前在客户端计算机上验证表单数据的方法。表单验证通常执行两个功能:

Basic Validation {#basic-validation}

First of all, the form must be checked to make sure all the mandatory fields are filled in. It just requires a loop through each field in the form to check for data.
首先,必须检查表单以确保填写所有必填字段。它只需要循环遍历表单中的每个字段以检查数据。

Data Format Validation {#data-format-validation}

Secondly, the data that is entered must be checked for correct form and value. Your code must include appropriate logic to test the correctness of the data.
其次,必须检查输入的数据的正确形式和值。您的代码必须包含适当的逻辑来测试数据的正确性。

Example: {#example-}

<html>
   
   <head>
      <title>Form Validation</title>
      
      <script type="text/javascript">
         <!--
            // Form validation code will come here.
         //-->
      </script>
      
   </head>
   
   <body>
      <form action="/cgi-bin/test.cgi" name="myForm" onsubmit="return(validate());">
         <table cellspacing="2" cellpadding="2" border="1">
            
            <tr>
               <td align="right">Name</td>
               <td><input type="text" name="Name" /></td>
            </tr>
            
            <tr>
               <td align="right">EMail</td>
               <td><input type="text" name="EMail" /></td>
            </tr>
            
            <tr>
               <td align="right">Zip Code</td>
               <td><input type="text" name="Zip" /></td>
            </tr>
            
            <tr>
               <td align="right">Country</td>
               <td>
                  <select name="Country">
                     <option value="-1" selected>[choose yours]</option>
                     <option value="1">USA</option>
                     <option value="2">UK</option>
                     <option value="3">INDIA</option>
                  </select>
               </td>
            </tr>
            
            <tr>
               <td align="right"></td>
               <td><input type="submit" value="Submit" /></td>
            </tr>
            
         </table>
      </form>
      
   </body>
</html>

Output {#output}

Have a look
看一看here.

Basic Form Validation {#basic-form-validation}

First let us see how to do a basic form validation. In the above form, we are calling validate() to validate data when the onsubmit event is occurring. The following code shows the implementation of this
首先让我们看看如何进行基本表单验证。在上面的表单中,我们调用validate()来在onsubmit事件发生时验证数据。以下代码显示了此实现validate()function.
功能。

<script type="text/javascript">
   // Form validation code will come here.
   function validate()
      {
      
         if( document.myForm.Name.value == "" )
         {
            alert( "Please provide your name!" );
            document.myForm.Name.focus() ;
            return false;
         }
         
         if( document.myForm.EMail.value == "" )
         {
            alert( "Please provide your Email!" );
            document.myForm.EMail.focus() ;
            return false;
         }
         
         if( document.myForm.Zip.value == "" ||
         isNaN( document.myForm.Zip.value ) ||
         document.myForm.Zip.value.length != 5 )
         {
            alert( "Please provide a zip in the format #####." );
            document.myForm.Zip.focus() ;
            return false;
         }
         
         if( document.myForm.Country.value == "-1" )
         {
            alert( "Please provide your country!" );
            return false;
         }
         return( true );
      }
</script>

Output {#output-1}

Have a look
看一看here.

Data Format Validation {#data-format-validation-1}

Now we will see how we can validate our entered form data before submitting it to the web server.
现在我们将看到如何在将输入的表单数据提交到Web服务器之前验证它们。

The following example shows how to validate an entered email address. An email address must contain at least an '@' sign and a dot (.). Also, the '@' must not be the first character of the email address, and the last dot must at least be one character after the '@' sign.
以下示例显示如何验证输入的电子邮件地址。电子邮件地址必须至少包含"@"符号和点(。)。此外,&#39;@&#39;不能是电子邮件地址的第一个字符,最后一个点必须至少是&#39;@&#39;符号后面的一个字符。

Example: {#example--1}

<script type="text/javascript">
    function validateEmail()
      {
         var emailID = document.myForm.EMail.value;
         atpos = emailID.indexOf("@");
         dotpos = emailID.lastIndexOf(".");
         
         if (atpos < 1 || ( dotpos - atpos < 2 )) 
         {
            alert("Please enter correct email ID")
            document.myForm.EMail.focus() ;
            return false;
         }
         return( true );
      }
</script>

Output {#output-2}

Have a look
看一看here.

HTML5 Form Constraints {#html5-form-constraints}

Some of the commonly used HTML5 constraints for
一些常用的HTML5约束<input> are the
是的type attribute (e.g.
属性(例如type="password"),
maxlength,
required and
disabled. A less commonly used constraint is the
。一个不太常用的约束是pattern attribute that takes a JavaScript regular expression.
采用JavaScript正则表达式的属性。

JavaScript If statement example {#javascript-if-statement-example}

The
if statement executes a statement if a specified condition is
如果指定的条件是,则语句执行语句true. If the condition is
。如果条件是false, another statement can be executed using the
,另一个语句可以使用else statement.
声明。

Note: The
else statement is optional.
声明是可选的。

if (condition)
    /* do something */
else
    /* do something else */

Multiple
if...else statements can be chained to create an
语句可以链接来创建else if clause. This specifies a new condition to test and can be repeated to test multiple conditions, checking until a true statement is presented to execute.
条款。这指定了要测试的新条件,可以重复测试多个条件,检查直到执行真正的语句。

if (condition1)
    /* do something */
else if (condition2)
    /* do something else */
else if (condition3)
    /* do something else */
else
    /* final statement */

Note: If you want to execute more than one statement in the
如果你想在中执行多个语句if,
else or
要么else if part, curly braces are required around the statements:
部分,语句周围需要花括号:

if (condition) {
    /* do */
    /* something */
    /* with multiple statements */
} else {
    /* do something */
    /* else */
}

MDN link |
|MSDN link

Examples {#examples-9}

Using
if...else:

    // If x=5 z=7 and q=42. If x is not 5 then z=19.
    if (x == 5) {
      z = 7;
      q = 42
    else
      z = 19;

Using
else if:

if (x < 10)
    return "Small number";
else if (x < 50)
    return "Medium number";
else if (x < 100)
    return "Large number";
else {
    flag = 1;
    return "Invalid number";
}

JavaScript Prototype Example {#javascript-prototype-example}

JavaScript is a prototype-based language, therefore understanding the prototype object is one of the most important concepts which JavaScript practitioners need to know.
JavaScript是一种基于原型的语言,因此理解原型对象是JavaScript从业者需要知道的最重要的概念之一。

This section will give you a short overview of the Prototype object through various examples. Before reading this part, you will need to have a basic understanding of the
本节将通过各种示例简要概述Prototype对象。在阅读本部分之前,您需要对该部分有一个基本的了解this reference in JavaScript.

Prototype object {#prototype-object}

For the sake of clarity, let's examine the following example:
为了清楚起见,我们来看看以下示例:

function Point2D(x, y) {
  this.x = x;
  this.y = y;
}

As
Point2D function is declared, a default property named
函数声明,默认属性名为prototype will be created for it (note that, in JavaScript, a function is also an object).
将为它创建(请注意,在JavaScript中,函数也是一个对象)。

The
prototype property is an object which contains a
property是一个包含a的对象constructorproperty and its value is
财产及其价值是Point2D function:
功能:Point2D.prototype.constructor = Point2D. And when you call
。当你打电话的时候Point2D with
new keyword,
关键词, newly created objects will inherit all properties from
Point2D.prototype.

To check that, you can add a method named
要检查它,您可以添加一个名为的方法move into
Point2D.prototype as follows:
如下:

Point2D.prototype.move = function(dx, dy) {
  this.x += dx;
  this.y += dy;
}

var p1 = new Point2D(1, 2);
p1.move(3, 4);
console.log(p1.x); // 4
console.log(p1.y); // 6

The
Point2D.prototype is called
叫做 prototype object or
要么 prototype of
p1 object and for any other object created with
对象以及使用的任何其他对象new Point2D(...) syntax. You can add more properties to
句法。您可以添加更多属性Point2D.prototype object as you like. The common pattern is to declare methods to
你想要的对象。常见的模式是声明方法Point2D.prototype and other properties will be declared in the constructor function.
和其他属性将在构造函数中声明。

Built-in objects in JavaScript are constructed in a similar manner. For example:
JavaScript中的内置对象以类似的方式构造。例如:

  • Prototype of objects created with new Object() or {} syntax is Object.prototype.
  • Prototype of arrays created with new Array() or [] syntax is Array.prototype.
  • And so on with other built-in objects such as Date and RegExp.

Object.prototype is inherited by all objects and it has no prototype (its prototype is
由所有对象继承,它没有原型(它的原型是null).
)。

Prototype chain {#prototype-chain}

The prototype chain mechanism is simple: When you access a property
原型链机制很简单:当您访问属性时p on object
在对象上obj, the JavaScript engine will search this property inside
,JavaScript引擎将在里面搜索这个属性obj object. If the engine fails to search, it continues searching in the prototype of
宾语。如果引擎无法搜索,它将继续搜索原型obj object and so on until reaching
对象等直到达到Object.prototype. If after the search has finished, and nothing has been found, the result will be
。如果搜索完成后,找不到任何内容,结果将是undefined. For example:
。例如:

var obj1 = {
  a: 1,
  b: 2
};

var obj2 = Object.create(obj1);
obj2.a = 2;

console.log(obj2.a); // 2
console.log(obj2.b); // 2
console.log(obj2.c); // undefined

In above snippet, the statement
在上面的片段中,声明var obj2 = Object.create(obj1) will create
将创造obj2 object with prototype
原型对象obj1 object. In other words,
宾语。换一种说法,obj1 becomes the prototype of
成为原型obj2 instead of
代替Object.prototype by default. As you can see,
默认。如你看到的,b is not a property of
不属于obj2; you can still access it via the prototype chain. For the
;你仍然可以通过原型链访问它。为了c property, however, you get an
但是,你得到一个undefined value because it can't be found in
价值,因为它无法找到obj1 and
Object.prototype.

Classes {#classes}

In ES2016, we now get to use the
在ES2016中,我们现在可以使用了Class keyword as well as the methods mentioned above to manipulate
关键字以及上面提到的操作方法prototype. The JavaScript
。 JavaScriptClass appeals to developers from OOP backgrounds, but it's essentially doing the same thing as above.
从OOP背景中吸引开发人员,但它基本上与上面做同样的事情。

class Rectangle {
  constructor(height, width) {
    this.height = height
    this.width = width
  }

  get area() {
    return this.calcArea()
  }

  calcArea() {
    return this.height * this.width
  }
}

const square = new Rectangle(10, 10)

console.log(square.area) // 100

This is basically the same as:
这基本上与以下相同:

function Rectangle(height, width) {
  this.height = height
  this.width = width
}

Rectangle.prototype.calcArea = function calcArea() {
  return this.height * this.width
}

The
getter and
setter methods in classes bind an Object property to a function that will be called when that property is looked up. It's just syntactic sugar to help make it easier to
类中的方法将Object属性绑定到将在查找该属性时调用的函数。它只是语法糖,以帮助使它更容易 look up or
要么 set properties.
属性。

JavaScript Scope Example {#javascript-scope-example}

If you've been programming in JavaScript for a while, you've undoubtedly run into a concept known as
如果你已经用JavaScript编程了一段时间,那么毫无疑问你会遇到一个被称为的概念scope. What is
。什么是scope? Why should you take the time to learn it?
?你为什么要花时间学习它?

In programmer speak,
在程序员说话,scope is the
是个 current context of execution . Confused? Let's take a look at the following piece of code:
。困惑?我们来看看下面这段代码:

var foo = 'Hi, I am foo!';

var baz = function () {
  var bar = 'Hi, I am bar too!';
    console.log(foo);
}

baz(); // Hi, I am foo!
console.log(bar); // ReferenceError...

This is a simple example, but it does a good job of illustrating what is known as
这是一个简单的例子,但它很好地说明了所谓的 Lexical scope . JavaScript, and almost every other programming language, has a
。 JavaScript和几乎所有其他编程语言都有 Lexical scope . There is another kind of scope known as
。还有另一种范围称为 Dynamic scope , but we won't be discussing that.
,但我们不会讨论这个问题。

Now, the term
现在,这个词 Lexical scope sounds fancy, but as you will see it's really simple in principle. In a Lexical Scope, there are two kinds of scopes: the
听起来很花哨,但正如你会看到它原则上非常简单。在词法范围中,有两种范围: global scope and a
和a local scope .

Before you type the first line of code in your program, a
在程序中键入第一行代码之前,a global scope is created for you. This contains all the variables that you declare in your program
是为你而创造的。它包含您在程序中声明的所有变量 outside any functions .

In the example above, the variable
在上面的例子中,变量foo is in the global scope of the program, while the variable
是变量的全局范围bar is declared inside a function and is therefore
在函数内声明,因此 in the local scope of that function .

Let's break down the example line by line. While you might be confused at this point, I promise you will have a much better understanding by the time you finish reading this.
让我们逐行分解示例。虽然你可能会在这一点上感到困惑,但我保证你读完这篇文章时会有更好的理解。

On line 1 we are declaring the variable
在第1行,我们声明变量foo. Nothing too fancy here. Let's call this a left-hand size (LHS) reference to
。这里没什么太花哨的。我们称之为左手大小(LHS)参考foo, because we are assigning a value to
,因为我们正在分配一个值foo and it's on the left-hand side of the
它位于左侧equal sign.
标志。

On line 3, we are declaring a function and assigning it to variable
在第3行,我们声明一个函数并将其赋值给变量baz. This is another LHS reference to
。这是LHS的另一个参考baz. We are assigning a value to it (remember, functions are values too!). This function is then called on line 8. This is a RHS, or a right-hand side reference to
。我们正在为它赋值(请记住,函数也是值!)。然后在第8行调用此函数。这是RHS或右侧参考baz. We are retrieving
。我们正在检索baz's value, which in this case is a function and then invoking it.
的值,在这种情况下是一个函数,然后调用它。

Another RHS reference to
另一个RHS参考baz would be if we assigned its value to another variable, for example
例如,如果我们将其值分配给另一个变量foo = baz. This would be a LHS reference to
。这将是LHS的参考foo and a RHS reference to
和RHS参考baz.

The LHS and RHS references might sound confusing, but they are important for discussing scope. Think of it this way: a LHS reference is assigning a value to the variable, while a RHS reference is retrieving the value of the variable. They're just a shorter and more convenient way of saying 'retrieving the value' and 'assigning a value'.
LHS和RHS参考文献可能听起来令人困惑,但它们对于讨论范围很重要。可以这样想:LHS参考是为变量赋值,而RHS参考是检索变量的值。它们只是一种更简单,更方便的方式来表示"检索价值"和"分配价值"。

Let's now break down what's happening inside the function itself.
现在让我们分解函数本身内部发生的事情。

When the compiler compiles the code inside a function, it enters the function's
当编译器在函数内部编译代码时,它会进入函数 local scope .

On line 4, the variable
在第4行,变量bar is declared. This is a LHS reference to
被宣布。这是LHS的参考bar. On the next line, we have a RHS reference to
。在下一行,我们有一个RHS参考foo inside the
在 - 的里面console.log(). Remember, we are retrieving
。请记住,我们正在检索foo's value and then passing it as an argument to the method
的值,然后将其作为参数传递给方法console.log().

When we have a RHS reference to
当我们有RHS参考时foo, the compiler looks for the declaration of the variable
,编译器查找变量的声明foo. The compiler doesn't find it in the function itself, or the
。编译器在函数本身或者函数中找不到它 function's local scope , so it
所以 goes up one level: to the global scope .

At this point you're probably thinking that scope has something to do with variables. That is correct. A scope can be thought of as a container for variables. All variables that are created within a local scope are only accessible in that local scope. However, all local scopes can access the global scope. (I know you're probably even more confused right now, but just bear with me for a few more paragraphs).
此时您可能认为范围与变量有关。那是对的。范围可以被视为变量的容器。在本地范围内创建的所有变量只能在该本地范围内访问。但是,所有本地范围都可以访问全局范围。 (我知道你现在可能会更加困惑,但只要跟我说几句话)。

So the compiler goes up to the global scope to find a LHS reference to the variable
因此,编译器进入全局范围以查找对变量的LHS引用foo. It finds one on line 1, so it retrieves the value from the LHS reference, which is a string:
。它在第1行找到一个,因此它从LHS引用中检索值,该引用是一个字符串:'Hi, I am foo!'. This string is sent to the
。这个字符串被发送到console.log() method, and outputted to the console.
方法,并输出到控制台。

The compiler has finished executing the code inside the function, so we come back out to line 9. On line 9, we have a RHS reference for the variable
编译器已经完成了函数内部的代码执行,所以我们回到第9行。在第9行,我们有一个变量的RHS参考bar.

Now,
现在,bar was declared in the local scope of
被宣布在当地范围内baz, but there is a RHS reference for
,但有一个RHS参考bar in the global scope. Since there is no LHS reference for
在全球范围内。由于没有LHS参考bar in the global scope, the compiler can't find a value for
在全局范围内,编译器找不到值bar and throws a ReferenceError.
并抛出一个ReferenceError。

But, you might ask, if the function can look outside itself for variables, or a local scope can peek into the global scope to find LHS references, why can't the global scope peek into a local scope? Well that's how lexical scope works!
但是,您可能会问,如果函数可以在变量外部查看,或者本地范围可以查看全局范围以查找LHS引用,为什么全局范围不能窥探到本地范围?那就是词汇范围的工作原理!

... // global scope
var baz = function() {
  ... // baz's scope
}
... /// global scope

This is the same code from above which illustrates the scope. This forms a sort of hierarchy that goes up to the global scope:
这是与上面相同的代码,用于说明范围。这形成了一种符合全球范围的层次结构:

baz -> global.

So, if there is a RHS reference for a variable inside
因此,如果内部存在变量的RHS参考baz's scope, it can be fulfilled by a LHS reference for that variable in the global scope. But the opposite is
的范围,可以通过全球范围内该变量的LHS参考来实现。但恰恰相反 not true .

What if we had another function inside
如果我们内部有另一个功能怎么办?baz?

... // global scope
var baz = function() {
  ... // baz's scope

  var bar = function() {
     ... // bar's scope.
  }

}
... /// global scope

In this case, the hierarchy or the
在这种情况下,层次结构或 scope chain would look like this:
看起来像这样:

bar -> baz -> global

Any RHS references inside
内部的任何RHS参考bar's local scope can be fulfilled by LHS references in the global scope or
本地范围可以通过全球范围内的LHS参考来实现baz's scope, but a RHS reference in
的范围,但RHS参考baz's scope cannot be fulfilled by a LHS reference in
LHS的参考资料无法满足其范围bar's scope.
的范围。

You can only traverse down a scope chain, not up.

There are other two important things you should know about JavaScript scopes.
关于JavaScript范围,您还应该了解其他两个重要事项。

  1. Scopes are declared by functions, not by blocks.
  2. Functions can be forward-referenced, variables can't.

Observe (each comment describes scope at the line that it's written on):
观察(每个评论描述其写入的行的范围):

    // outer() is in scope here because functions can be forward-referenced
    
    function outer() {
    
        // only inner() is in scope here
        // because only functions are forward-referenced
    
        var a = 1;
        
        //now 'a' and inner() are in scope
        
        function inner() {
            var b = 2
            
            if (a == 1) {
                var c = 3;
            }
            
            // 'c' is still in scope because JavaScript doesn't care
            // about the end of the 'if' block, only function inner()
        }
        
        // now b and c are out of scope
        // a and inner() are still in scope
        
    }
    
    // here, only outer() is in scope

JavaScript For Loop Example {#javascript-for-loop-example}

Syntax {#syntax-8}

for ([initialization]); [condition]; [final-expression]) {
   // statement
}

The javascript
javascriptfor statement consists of three expressions and a statement:
语句由三个表达式和一个语句组成:

  • initialization - Run before the first execution on the loop. This expression is commonly used to create counters. Variables created here are scoped to the loop. Once the loop has finished its execution, they are destroyed.
  • condition - Expression that is checked prior to the execution of every iteration. If omitted, this expression evaluates to true. If it evaluates to true, the loop's statement is executed. If it evaluates to false, the loop stops.
  • final-expression - Expression that is run after every iteration. Usually used to increment a counter. But it can be used to decrement a counter too.
  • statement - Code to be repeated in the loop

any of these three expressions or the statement can be omitted. For loops are commonly used to count a certain number of iterations to repeat a statement. Use a
这三个表达式中的任何一个或语句都可以省略。 For循环通常用于计算一定数量的迭代以重复语句。用一个break statement to exit the loop before the condition expression evaluates to false.
语句表达式求值为false之前退出循环的语句。

Common Pitfalls {#common-pitfalls}

Exceeding the bounds of an array

When indexing over an array many times, it is easy to exceed the bounds of the array (ex. try to reference the 4th element of a 3 element array).
在对数组进行多次索引时,很容易超出数组的边界(例如,尝试引用3元素数组的第4个元素)。

    // This will cause an error.
    // The bounds of the array will be exceeded.
    var arr = [ 1, 2, 3 ];
    for (var i = 0; i <= arr.length; i++) {
       console.log(arr[i]);
    }

    output:
    1
    2
    3
    undefined

There are two ways to fix this code. Set the condition to either
有两种方法可以修复此代码。将条件设置为i < arr.length or
要么i <= arr.length - 1

Examples {#examples-10}

Iterate through integers from 0-8
迭代0-8的整数

for (var i = 0; i < 9; i++) {
   console.log(i);
}

output:
0
1
2
3
4
5
6
7
8

Break out of a loop before condition expression is false
在条件表达式为false之前中断循环

for (var elephant = 1; elephant < 10; elephant+=2) {
    if (elephant === 7) {
        break;
    }
    console.info('elephant is ' + elephant);
}

output:
elephant is 1
elephant is 3
elephant is 5

JavaScript Break Statement Example {#javascript-break-statement-example}

The
break statement terminates the current loop,
语句终止当前循环,switch or
要么label statement and transfers program control to the statement following the terminated statement.
声明并将程序控制转移到终止声明之后的声明。

break;

If the
如果 break statement is used in a labeled statement, the syntax is as follows:
语句用于带标签的语句,语法如下:

break labelName;

Examples {#examples-11}

The following function has a
以下功能有一个 break statement that terminates the
声明终止while loop when
循环时 i is 3, and then returns the value
是3,然后返回值 3 * x .

function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      break;
    }
    i += 1;
  }

  return i * x;
}

In the following example, the counter is set up to count from 1 to 99; however, the
在以下示例中,计数器设置为从1到99计数;但是,那 break statement terminates the loop after 14 counts.
语句在14次计数后终止循环。

for (var i = 1; i < 100; i++) {
  if (i == 15) {
    break;
  }
}

JavaScript Do While loop example {#javascript-do-while-loop-example}

The
do...while loop is closely related to the
循环与之密切相关while loop. In the do while loop, the condition is checked at the end of the loop.
环。在do while循环中,在循环结束时检查条件。

Here is the
这里是 syntax for
对于do...while loop:
环:

Syntax: {#syntax-}

 do {

   *Statement(s);*

} while (*condition*);

statement(s): A statement that is executed
执行的语句 at least once before the condition or Boolean expression is evaluated and is re-executed each time the condition evaluates to true.
在计算条件或布尔表达式之前,每次条件计算结果为true时重新执行。

condition: Here, a condition is a Boolean expression. If the Boolean expression evaluates to true, the statement is executed again. When the Boolean expression evaluates to false, the loops ends.
这里,条件是布尔表达式。如果布尔表达式的计算结果为true,则再次执行该语句。当布尔表达式的计算结果为false时,循环结束。

Example: {#example--2}

var i = 0;
do {
  i = i + 1;
  console.log(i);
} while (i < 5);

Output:
1
2
3
4
5

JavaScript For In Loop Example {#javascript-for-in-loop-example}

The
for...in statement iterates over the enumerable properties of an object, in arbitrary order. For each distinct property, statements can be executed.
语句以任意顺序迭代对象的可枚举属性。对于每个不同的属性,可以执行语句。

for (variable in object) {
...
}

Required/OptionalParameterDescriptionRequiredVariable: A different property name is assigned to the variable on each iteration. OptionalObject: an object whose enumerable properties are iterated.
必需/ OptionalParameterDescriptionRequiredVariable:在每次迭代时为变量分配不同的属性名称。 OptionalObject:迭代其可枚举属性的对象。

Examples {#examples-12}

// Initialize object.
a = { "a": "Athens", "b": "Belgrade", "c": "Cairo" }

// Iterate over the properties.
var s = ""
for (var key in a) {
    s += key + ": " + a[key];
    s += "<br />";
    }
document.write (s);

// Output:
// a: Athens
// b: Belgrade
// c: Cairo

// Initialize the array.
var arr = new Array("zero", "one", "two");

// Add a few expando properties to the array.
arr["orange"] = "fruit";
arr["carrot"] = "vegetable";

// Iterate over the properties and elements.
var s = "";
for (var key in arr) {
    s += key + ": " + arr[key];
    s += "<br />";
}

document.write (s);

// Output:
//   0: zero
//   1: one
//   2: two
//   orange: fruit
//   carrot: vegetable

// Efficient way of getting an object's keys using an expression within the for-in loop's conditions
var myObj = {a: 1, b: 2, c:3}, myKeys = [], i=0;
for (myKeys[i++] in myObj);

document.write(myKeys);

//Output:
//   a
//   b
//   c

JavaScript For Of Loop Example {#javascript-for-of-loop-example}

The
for...of statement creates a loop iterating over iterable objects (including Array, Map, Set, Arguments object and so on), invoking a custom iteration hook with statements to be executed for the value of each distinct property.
语句创建循环迭代可迭代对象(包括Array,Map,Set,Arguments对象等),调用自定义迭代挂钩,其中包含要为每个不同属性的值执行的语句。

    for (variable of object) {
        statement
    }

Description variable: On each iteration a value of a different property is assigned to the variable.object Object whose enumerable properties are iterated.
描述变量:在每次迭代时,将不同属性的值赋给variable.object对象,该对象的可枚举属性将被迭代。

Examples {#examples-13}

Array {#array}

    let arr = [ "fred", "tom", "bob" ];

    for (let i of arr) {
        console.log(i);
    }

    // Output:
    // fred
    // tom
    // bob

Map {#map-function map() { [native code] }1}

    var m = new Map();
    m.set(1, "black");
    m.set(2, "red");

    for (var n of m) {
        console.log(n);
    }

    // Output:
    // 1,black
    // 2,red

Set {#set}

    var s = new Set();
    s.add(1);
    s.add("red");

    for (var n of s) {
        console.log(n);
    }

    // Output:
    // 1
    // red

Arguments object {#arguments-object}

    // your browser must support for..of loop
    // and let-scoped variables in for loops

    function displayArgumentsObject() {
        for (let n of arguments) {
            console.log(n);
        }
    }


    displayArgumentsObject(1, 'red');

    // Output:
    // 1
    // red

JavaScript While Loop Example {#javascript-while-loop-example}

The while loop starts by evaluating the condition. If the condition is true, the statement(s) is/are executed. If the condition is false, the statement(s) is/are not executed. After that, while loop ends.
while循环首先评估条件。如果条件为真,则执行语句。如果条件为假,则不执行语句。之后,while循环结束。

Here is the
这里是 syntax for the while loop:
对于while循环:

Syntax: {#syntax--1}

while (condition)

{

  statement(s);

}

statement(s): A statement that is executed as long as the condition evaluates to true.
只要条件计算为true就执行的语句。

condition: Here, the condition is a Boolean expression which is evaluated before each pass through the loop. If this condition evaluates to true, statement(s) is/are executed. When the condition evaluates to false, execution continues with the statement after the while loop.
这里,条件是一个布尔表达式,在每次循环之前计算。如果此条件的计算结果为true,则执行语句。当条件求值为false时,继续执行while循环后的语句。

Example: {#example--3}

    var i = 1;
    while (i < 10) 
    {
      console.log(i);
       i++; // i=i+1 same thing
    }

    Output:
    1 
    2 
    3 
    4
    5
    6
    7
    8
    9

中英文模式阅读
中文模式阅读
英文模式阅读

查看英文原文

查看更多文章

公众号:银河系1号
公众号:银河系1号

联系邮箱:public@space-explore.com
联系邮箱:public@space-explore.com

(未经同意,请勿转载)
(未经同意,请勿转载)