了解JavaScript中的范围

介绍 ( Introduction )

JavaScript has a feature called Scope. Though the concept of scope is not that easy to understand for many new developers, I will try my best to explain them to you in the simplest scope. Understanding scope will make your code stand out, reduce errors and help you make powerful design patterns with it.

JavaScript具有称为Scope的功能。 尽管对于许多新开发人员而言,范围的概念并不是那么容易理解,但是我将尽力在最简单的范围内向您解释它们。 了解scope将使您的代码脱颖而出,减少错误并帮助您使用它来构建强大的设计模式。

什么是范围? ( What is Scope? )

Scope is the accessibility of variables, functions, and objects in some particular part of your code during runtime. In other words, scope determines the visibility of variables and other resources in areas of your code.

范围是运行时在代码某些特定部分中变量,函数和对象的可访问性。 换句话说,范围决定了代码区域中变量和其他资源的可见性。

为什么范围? 最少访问原则 ( Why Scope? The Principle of Least Access )

So, what's the point in limiting the visibility of variables and not having everything available everywhere in your code? One advantage is that scope provides some level of security to your code. One common principle of computer security is that users should only have access to the stuff they need at a time.

那么,限制变量的可见性以及在代码中的所有地方都没有可用的东西又有什么意义呢? 优势之一是范围为您的代码提供了一定程度的安全性。 计算机安全性的一个普遍原则是,用户一次只能访问他们需要的东西。

Think of computer administrators. As they have a lot of control over the company's systems, it might seem okay to grant full access user account to them. Suppose you have a company with three administrators, all of them having full access to the systems and everything is working smooth. But suddenly something bad happens and one of your system gets infected with a malicious virus. Now you don't know whose mistake that was? You realize that you should them basic user accounts and only grant full access privileges when needed. This will help you track changes and keep an account of who did what. This is called The Principle of Least Access. Seems intuitive? This principle is also applied to programming language designs, where it is called scope in most programming languages including JavaScript which we are going to study next.

想想计算机管理员。 由于他们对公司的系统有很多控制权,因此可以向他们授予完全访问权限用户帐户似乎不错。 假设您有一家拥有三名管理员的公司,他们所有人都拥有对系统的完全访问权限,并且一切运行顺利。 但是突然发生了一些不好的事情,并且您的系统之一感染了恶意病毒。 现在您不知道那是谁的错误? 您意识到应该使用基本用户帐户,并且仅在需要时才授予完全访问权限。 这将帮助您跟踪更改并记下谁做了什么。 这称为最小访问原则。 看起来很直观? 该原理也适用于编程语言设计,在大多数编程语言(包括我们接下来将要研究JavaScript)中被称为作用域。

As you continue on in your programming journey, you will realize that scoping parts of your code helps improve efficiency, track bugs and reduce them. Scope also solves the naming problem when you have variables with the same name but in different scopes. Remember not to confuse scope with context. They are both different features.

在继续进行编程的过程中,您将意识到对代码部分进行范围界定有助于提高效率,跟踪错误并减少错误。 当您拥有名称相同但作用域不同的变量时,作用域还解决了命名问题。 切记不要将范围与上下文混淆。 它们都是不同的功能。

JavaScript的范围 ( Scope in JavaScript )

In the JavaScript language there are two types of scopes:

在JavaScript语言中,作用域有两种:

  • Global Scope

    全球范围
  • Local Scope

    当地范围

Variables defined inside a function are in local scope while variables defined outside of a function are in the global scope. Each function when invoked creates a new scope.

在函数内部定义的变量在局部范围内,而在函数外部定义的变量在全局范围内。 每个函数在调用时都会创建一个新的作用域。

全球范围 ( Global Scope )

When you start writing JavaScript in a document, you are already in the Global scope. There is only one Global scope throughout a JavaScript document. A variable is in the Global scope if it's defined outside of a function.

当您开始在文档中编写JavaScript时,您已经处于Global范围内。 整个JavaScript文档中只有一个Global范围。 如果在函数外部定义变量,则该变量在Global范围内。

// the scope is by default global
var name = 'Hammad';

Variables inside the Global scope can be accessed and altered in any other scope.

可以在任何其他范围内访问和更改全局范围内的变量。

var name = 'Hammad';

console.log(name); // logs 'Hammad'

function logName() {
    console.log(name); // 'name' is accessible here and everywhere else
}

logName(); // logs 'Hammad'

当地范围 ( Local Scope )

Variables defined inside a function are in the local scope. And they have a different scope for every call of that function. This means that variables having the same name can be used in different functions. This is because those variables are bound to their respective functions, each having different scopes, and are not accessible in other functions.

函数内部定义的变量在本地范围内。 对于该函数的每次调用,它们具有不同的作用域。 这意味着具有相同名称的变量可以在不同的函数中使用。 这是因为这些变量绑定到各自的函数,每个函数具有不同的作用域,并且在其他函数中不可访问。

// Global Scope
function someFunction() {
    // Local Scope #1
    function someOtherFunction() {
        // Local Scope #2
    }
}

// Global Scope
function anotherFunction() {
    // Local Scope #3
}
// Global Scope

禁止声明 ( Block Statements )

Block statements like if and switch conditions or for and while loops, unlike functions, don't create a new scope. Variables defined inside of a block statement will remain in the scope they were already in.

与函数不同,诸如ifswitch条件或forwhile循环之类的语句块不会创建新的作用域。 在block语句内部定义的变量将保留在它们已经存在的范围内。

if (true) {
    // this 'if' conditional block doesn't create a new scope
    var name = 'Hammad'; // name is still in the global scope
}

console.log(name); // logs 'Hammad'

ECMAScript 6 introduced the let and const keywords. These keywords can be used in place of the var keyword.

ECMAScript 6引入了letconst关键字。 可以使用这些关键字代替var关键字。

var name = 'Hammad';

let likes = 'Coding';
const skills = 'Javascript and PHP';

Contrary to the var keyword, the let and const keywords support the declaration of local scope inside block statements.

var关键字相反, letconst关键字支持在块语句中声明局部作用域。

if (true) {
    // this 'if' conditional block doesn't create a scope

    // name is in the global scope because of the 'var' keyword
    var name = 'Hammad';
    // likes is in the local scope because of the 'let' keyword
    let likes = 'Coding';
    // skills is in the local scope because of the 'const' keyword
    const skills = 'JavaScript and PHP';
}

console.log(name); // logs 'Hammad'
console.log(likes); // Uncaught ReferenceError: likes is not defined
console.log(skills); // Uncaught ReferenceError: skills is not defined

Global scope lives as long as your application lives. Local Scope lives as long as your functions are called and executed.

只要您的应用程序存在,全局范围就存在。 只要您的函数被调用和执行,Local Scope就会存在。

语境 ( Context )

Many developers often confuse scope and context as if they equally refer to the same concepts. But this is not the case. Scope is what we discussed above and Context is used to refer to the value of this in some particular part of your code. Scope refers to the visibility of variables and context refers to the value of this in the same scope. We can also change the context using function methods, which we will discuss later. In the global scope context is always the Window object.

许多开发人员经常混淆范围和上下文,就像他们等同地引用相同的概念一样。 但这种情况并非如此。 适用范围是什么,我们上面已讨论并上下文用于指代的价值this在你的代码的某些特定部分。 范围是指变量的可见性,上下文是指在相同范围内this变量的值。 我们还可以使用函数方法来更改上下文,我们将在后面讨论。 在全局范围内,上下文始终是Window对象。

// logs: Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage…}
console.log(this);

function logFunction() {
    console.log(this);
}
// logs: Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage…}
// because logFunction() is not a property of an object
logFunction(); 

If scope is in the method of an object, context will be the object the method is part of.

如果作用域在对象的方法中,则上下文将是方法所在的对象。

class User {
    logName() {
        console.log(this);
    }
}

(new User).logName(); // logs User {}

(new User).logName() is a short way of storing your object in a variable and then calling the logName function on it. Here, you don't need to create a new variable.

(新用户).logName()是将对象存储在变量中,然后在其上调用logName函数的一种简短方法。 在这里,您无需创建新变量。

One thing you'll notice is that the value of context behaves differently if you call your functions using the new keyword. The context will then be set to the instance of the called function. Consider one of the examples above with the function called with the new keyword.

您会注意到的一件事是,如果您使用new关键字调用函数,则context的值会有所不同。 然后将上下文设置为被调用函数的实例。 考虑上面的示例之一,该函数使用new关键字调用。

function logFunction() {
    console.log(this);
}

new logFunction(); // logs logFunction {}

When a function is called in Strict Mode, the context will default to undefined.

严格模式下调用函数时,上下文默认为未定义。

执行上下文 ( Execution Context )

To remove all confusions and from what we studied above, the word context in Execution Context refers to scope and not context. This is a weird naming convention but because of the JavaScipt specification, we are tied to it.

要删除所有的混乱,并从我们上面的研究,在执行上下文语境一词指的是范围,而不是背景。 这是一个怪异的命名约定,但是由于JavaScipt规范,我们受到约束。

JavaScript is a single-threaded language so it can only execute a single task at a time. The rest of the tasks are queued in the Execution Context. As I told you earlier that when the JavaScript interpreter starts to execute your code, the context (scope) is by default set to be global. This global context is appended to your execution context which is actually the first context that starts the execution context.

JavaScript是一种单线程语言,因此它一次只能执行一个任务。 其余任务在执行上下文中排队。 如前所述,当JavaScript解释器开始执行代码时,默认情况下上下文(作用域)设置为全局。 此全局上下文将附加到您的执行上下文,该上下文实际上是启动执行上下文的第一个上下文。

After that, each function call (invocation) would append its context to the execution context. The same thing happens when an another function is called inside that function or somewhere else.

之后,每个函数调用(调用)都将其上下文附加到执行上下文。 当在另一个函数内部或另一个函数中调用另一个函数时,也会发生同样的事情。

Each function creates its own execution context.

每个函数创建自己的执行上下文。

Once the browser is done with the code in that context, that context will then be popped off from the execution context and the state of the current context in the execution context will be transferred to the parent context. The browser always executes the execution context that is at the top of the execution stack (which is actually the innermost level of scope in your code).

一旦浏览器完成了该上下文中的代码,该上下文便会从执行上下文中弹出,并且执行上下文中当前上下文的状态将转移到父上下文。 浏览器始终执行位于执行堆栈顶部的执行上下文(实际上是代码中作用域的最内层)。

There can only be one global context but any number of function contexts.

只能有一个全局上下文,但可以有任意数量的函数上下文。

The execution context has two phases of creation and code execution.

执行上下文具有创建和代码执行两个阶段。

创作阶段 (Creation Phase)

The first phase that is the creation phase is present when a function is called but its code is not yet executed. Three main things that happen in the creation phase are:

当调用一个函数但尚未执行其代码时,存在创建阶段的第一阶段。 在创建阶段发生的三件事是:

  • Creation of the Variable (Activation) Object,

    创建变量(激活)对象,
  • Creation of the Scope Chain, and

    范围链的创建,以及
  • Setting of the value of context (this)

    设置上下文值( this
可变对象 (Variable Object)

The Variable Object, also known as the activation object, contains all of the variables, functions and other declarations that are defined in a particular branch of the execution context. When a function is called, the interpreter scans it for all resources including function arguments, variables, and other declarations. Everything, when packed into a single object, becomes the the Variable Object.

变量对象,也称为激活对象,包含在执行上下文的特定分支中定义的所有变量,函数和其他声明。 调用函数时,解释器将扫描它的所有资源,包括函数参数,变量和其他声明。 一切都打包成一个对象,就变成了变量对象。

'variableObject': {
    // contains function arguments, inner variable and function declarations
}
范围链 (Scope Chain)

In the creation phase of the execution context, the scope chain is created after the variable object. The scope chain itself contains the variable object. The Scope Chain is used to resolve variables. When asked to resolve a variable, JavaScript always starts at the innermost level of the code nest and keeps jumping back to the parent scope until it finds the variable or any other resource it is looking for. The scope chain can simply be defined as an object containing the variable object of its own execution context and all the other execution contexts of it parents, an object having a bunch of other objects.

在执行上下文的创建阶段,作用域链是在变量对象之后创建的。 范围链本身包含变量对象。 范围链用于解析变量。 当要求解析变量时,JavaScript总是从代码嵌套的最内层开始,并不断跳回到父级作用域,直到找到变量或要查找的任何其他资源。 范围链可以简单地定义为包含其自身执行上下文的变量对象及其父对象的所有其他执行上下文的对象,该对象具有一堆其他对象。

'scopeChain': {
    // contains its own variable object and other variable objects of the parent execution contexts
}
执行上下文对象 (The Execution Context Object)

The execution context can be represented as an abstract object like this:

执行上下文可以表示为一个抽象对象,如下所示:

executionContextObject= {
    'scopeChain': {}, // contains its own variableObject and other variableObject of the parent execution contexts
    'variableObject': {}, // contains function arguments, inner variable and function declarations
    'this': valueOfThis
}

代码执行阶段 (Code Execution Phase)

In the second phase of the execution context, that is the code execution phase, other values are assigned and the code is finally executed.

在执行上下文的第二阶段,即代码执行阶段,分配其他值,并最终执行代码。

词汇范围 ( Lexical Scope )

Lexical Scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. This means that the child functions are lexically bound to the execution context of their parents. Lexical scope is sometimes also referred to as Static Scope.

词法作用域意味着在一组嵌套函数中,内部函数可以访问其父作用域的变量和其他资源。 这意味着子功能按词法绑定到其父项的执行上下文。 词汇范围有时也称为静态范围。

function grandfather() {
    var name = 'Hammad';
    // likes is not accessible here
    function parent() {
        // name is accessible here
        // likes is not accessible here
        function child() {
            // Innermost level of the scope chain
            // name is also accessible here
            var likes = 'Coding';
        }
    }
}

The thing you will notice about lexical scope is that it works forward, meaning name can be accessed by its children's execution contexts. But it doesn't work backward to its parents, meaning that the variable likes cannot be accessed by its parents. This also tells us that variables having the same name in different execution contexts gain precedence from top to bottom of the execution stack. A variable, having a name similar to another variable, in the innermost function (topmost context of the execution stack) will have higher precedence.

您将注意到的关于词法范围的事情是它向前工作,这意味着可以通过其子级的执行上下文访问name 。 但是它不能向其父级倒退,这意味着其父级无法访问likes的变量。 这也告诉我们,在不同执行上下文中具有相同名称的变量从执行堆栈的顶部到底部获得优先级。 最里面的函数(执行堆栈的最上层上下文)中具有与另一个变量相似名称的变量将具有更高的优先级。

关闭 ( Closures )

The concept of closures is closely related to Lexical Scope, which we studied above. A Closure is created when an inner function tries to access the scope chain of its outer function meaning the variables outside of the immediate lexical scope. Closures contain their own scope chain, the scope chain of their parents and the global scope.

闭包的概念与我们上面研究的词法范围密切相关。 当内部函数尝试访问其外部函数的作用域链时,即表示闭包,这意味着变量位于直接词法作用域之外。 闭包包含它们自己的范围链,其父级的范围链和全局范围。

A closure can not only access the variables defined in its outer function but also the arguments of the outer function.

闭包不仅可以访问其外部函数中定义的变量,还可以访问外部函数的参数。

A closure can also access the variables of its outer function even after the function has returned. This allows the returned function to maintain access to all the resources of the outer function.

即使函数返回后,闭包也可以访问其外部函数的变量。 这允许返回的函数维护对外部函数的所有资源的访问。

When you return an inner function from a function, that returned function will not be called when you try to call the outer function. You must first save the invocation of the outer function in a separate variable and then call the variable as a function. Consider this example:

当您从一个函数返回一个内部函数时,当您尝试调用外部函数时,该返回的函数将不会被调用。 您必须首先将外部函数的调用保存在单独的变量中,然后将变量作为函数调用。 考虑以下示例:

function greet() {
    name = 'Hammad';
    return function () {
        console.log('Hi ' + name);
    }
}

greet(); // nothing happens, no errors

// the returned function from greet() gets saved in greetLetter
greetLetter = greet();

 // calling greetLetter calls the returned function from the greet() function
greetLetter(); // logs 'Hi Hammad'

The key thing to note here is that greetLetter function can access the name variable of the greet function even after it has been returned. One way to call the returned function from the greet function without variable assignment is by using parentheses () two times ()() like this:

这里要注意的关键是that greetLetter即使返回that greetLetter函数,也可以访问greet函数的name变量。 在没有变量分配的情况下从greet函数调用返回函数的一种方法是使用两次括号() ()()如下所示:

function greet() {
    name = 'Hammad';
    return function () {
        console.log('Hi ' + name);
    }
}

greet()(); // logs 'Hi Hammad'

公共和私人范围 ( Public and Private Scope )

In many other programming languages, you can set the visibility of properties and methods of classes using public, private and protected scopes. Consider this example using the PHP language:

在许多其他编程语言中,您可以使用公共,私有和受保护范围设置属性和类方法的可见性。 考虑使用PHP语言的示例:

// Public Scope
public $property;
public function method() {
  // ...
}

// Private Sccpe
private $property;
private function method() {
  // ...
}

// Protected Scope
protected $property;
protected function method() {
  // ...
}

Encapsulating functions from the public (global) scope saves them from vulnerable attacks. But in JavaScript, there is no such thing as public or private scope. However, we can emulate this feature using closures. To keep everything separate from the global we must first encapsulate our functions within a function like this:

从公共(全局)范围封装功能可以使它们免受易受攻击的攻击。 但是在JavaScript中,没有公共或私有作用域。 但是,我们可以使用闭包来模拟此功能。 为了使一切与全局分离,我们必须首先将函数封装在这样的函数中:

(function () {
  // private scope
})();

The parenthesis at the end of the function tells the interpreter to execute it as soon as it reads it without invocation. We can add functions and variables in it and they will not accessible outside. But what if we want to access them outside, meaning we want some of them to be public and some of them to be private? One type of closure, we can use, is called the Module Pattern which allows us to scope our functions using both public and private scopes in an object.

函数末尾的括号告诉解释器在读取它而无需调用的情况下立即执行它。 我们可以在其中添加函数和变量,并且无法从外部访问它们。 但是,如果我们想在外部访问它们,这意味着我们希望其中一些是公开的,而另一些是私有的呢? 我们可以使用的一种闭包类型称为模块模式,它允许我们使用对象中的公共范围和私有范围来对函数进行范围设置。

模块模式 (The Module Pattern)

The Module Pattern looks like this:

模块模式如下所示:

var Module = (function() {
    function privateMethod() {
        // do something
    }

    return {
        publicMethod: function() {
            // can call privateMethod();
        }
    };
})();

The return statement of the Module contains our public functions. The private functions are just those that are not returned. Not returning functions makes them inaccessible outside of the Module namespace. But our public functions can access our private functions which make them handy for helper functions, AJAX calls, and other things.

模块的return语句包含我们的公共功能。 私有函数就是那些不返回的函数。 不返回函数会使它们在Module名称空间之外不可访问。 但是我们的公共功能可以访问我们的私有功能,这使它们可以方便地使用辅助功能,AJAX调用和其他功能。

Module.publicMethod(); // works
Module.privateMethod(); // Uncaught ReferenceError: privateMethod is not defined

One convention is to begin private functions with an underscore, and returning an anonymous object containing our public functions. This makes them easy to manage in a long object. This is how it looks:

一种约定是用下划线开始私有函数,并返回包含我们公共函数的匿名对象。 这使得它们很容易在长对象中进行管理。 看起来是这样的:

var Module = (function () {
    function _privateMethod() {
        // do something
    }
    function publicMethod() {
        // do something
    }
    return {
        publicMethod: publicMethod,
    }
})();

立即调用函数表达式(IIFE) (Immediately-Invoked Function Expression (IIFE))

Another type of closure is the Immediately-Invoked Function Expression (IIFE). This is a self-invoked anonymous function called in the context of window, meaning that the value of this is set window. This exposes a single global interface to interact with. This is how it looks:

另一种闭包类型是立即调用函数表达式(IIFE)。 这就是所谓的在窗口的背景下,自调用匿名函数,这意味着价值this设置window 。 这公开了一个单独的全局接口与之交互。 看起来是这样的:

(function(window) {
    // do anything
})(this);

使用.call()、. apply()和.bind()更改上下文 ( Changing Context with .call(), .apply() and .bind() )

Call and Apply functions are used to change the context while calling a function. This gives you incredible programming capabilities (and some ultimate powers to Rule The World). To use the call or apply function, you just need to call it on the function instead of invoking the function using a pair of parenthesis and pass the context as the first argument. The function's own arguments can be passed after the context.

调用和应用函数用于在调用函数时更改上下文。 这为您提供了令人难以置信的编程功能(以及“ 统治世界”的某些最终能力)。 要使用call或apply函数,您只需要在函数上调用它,而不是使用一对括号调用该函数并将上下文作为第一个参数传递。 该函数自己的参数可以在上下文之后传递。

function hello() {
    // do something...
}

hello(); // the way you usually call it
hello.call(context); // here you can pass the context(value of this) as the first argument
hello.apply(context); // here you can pass the context(value of this) as the first argument

The difference between .call() and .apply() is that in Call, you pass the rest of the arguments as a list separated by a comma while apply allows you to pass the arguments in an array.

.apply() .call().apply()之间的区别在于,在Call中,您将其余参数作为以逗号分隔的列表进行传递,而apply则允许您在数组中传递参数。

function introduce(name, interest) {
    console.log('Hi! I\'m '+ name +' and I like '+ interest +'.');
    console.log('The value of this is '+ this +'.')
}

introduce('Hammad', 'Coding'); // the way you usually call it
introduce.call(window, 'Batman', 'to save Gotham'); // pass the arguments one by one after the contextt
introduce.apply('Hi', ['Bruce Wayne', 'businesses']); // pass the arguments in an array after the context

// Output:
// Hi! I'm Hammad and I like Coding.
// The value of this is [object Window].
// Hi! I'm Batman and I like to save Gotham.
// The value of this is [object Window].
// Hi! I'm Bruce Wayne and I like businesses.
// The value of this is Hi.

Call is slightly faster in performance than Apply.

通话的性能比Apply稍快一些。

The following example takes a list of items in the document and logs them to the console one by one.

以下示例获取文档中的项目列表,并将它们逐个记录到控制台。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Things to learn</title>
</head>
<body>
    <h1>Things to Learn to Rule the World</h1>
    <ul>
        <li>Learn PHP</li>
        <li>Learn Laravel</li>
        <li>Learn JavaScript</li>
        <li>Learn VueJS</li>
        <li>Learn CLI</li>
        <li>Learn Git</li>
        <li>Learn Astral Projection</li>
    </ul>
    <script>
        // Saves a NodeList of all list items on the page in listItems
        var listItems = document.querySelectorAll('ul li');
        // Loops through each of the Node in the listItems NodeList and logs its content
        for (var i = 0; i < listItems.length; i++) {
          (function () {
            console.log(this.innerHTML);
          }).call(listItems[i]);
        }

        // Output logs:
        // Learn PHP
        // Learn Laravel
        // Learn JavaScript
        // Learn VueJS
        // Learn CLI
        // Learn Git
        // Learn Astral Projection
    </script>
</body>
</html>

The HTML only contains an unordered list of items. The JavaScript then selects all of them from the DOM. The list is looped over till the end of the items in the list. Inside the loop, we log the content of the list item to the console.

HTML仅包含项目的无序列表。 然后,JavaScript从DOM中选择所有它们。 列表一直循环到列表中项目的末尾。 在循环内部,我们将列表项的内容记录到控制台。

This log statement is wrapped in a function wrapped in parentheses on which the call function is called. The corresponding list item is passed to the call function so that the the keyword in the console statement logs the innerHTML of the correct object.

该日志语句包装在括号中的函数中,在该函数中调用了call函数。 相应的列表项将传递给调用函数,以便控制台语句中the关键字记录正确对象的innerHTML。

Objects can have methods, likewise functions being objects can also have methods. In fact, a JavaScript function comes with four built-in methods which are:

对象可以具有方法,同样,作为对象的函数也可以具有方法。 实际上,JavaScript函数带有四个内置方法,它们是:

  • Function.prototype.apply()

    Function.prototype.apply()
  • Function.prototype.bind() (Introduced in ECMAScript 5 (ES5))

    Function.prototype.bind()(在ECMAScript 5(ES5)中引入)
  • Function.prototype.call()

    Function.prototype.call()
  • Function.prototype.toString()

    Function.prototype.toString()

Function.prototype.toString() returns a string representation of the source code of the function.

Function.prototype.toString()返回函数源代码的字符串表示形式。

Till now, we have discussed .call(), .apply(), and toString(). Unlike Call and Apply, Bind doesn't itself call the function, it can only be used to bind the value of context and other arguments before calling the function. Using Bind in one of the examples from above:

到目前为止,我们已经讨论.call() .apply()toString() 。 与Call and Apply不同,Bind本身不会调用该函数,它只能用于在调用该函数之前绑定上下文和其他参数的值。 在上述示例之一中使用Bind:

(function introduce(name, interest) {
    console.log('Hi! I\'m '+ name +' and I like '+ interest +'.');
    console.log('The value of this is '+ this +'.')
}).bind(window, 'Hammad', 'Cosmology')();

// logs:
// Hi! I'm Hammad and I like Cosmology.
// The value of this is [object Window].

Bind is like the call function, it allows you pass the rest of the arguments one by one separated by a comma and not like apply, in which you pass the arguments in an array.

Bind类似于call函数,它允许您将其余参数一一传递,并以逗号分隔,而不像apply那样在数组中传递参数。

结论 ( Conclusion )

These concepts are radical to JavaScript and important to understand if you want to approach more advanced topics. I hope you got a better understanding of JavaScript Scope and things around it. If something just didn't click, feel free to ask in the comments below.

这些概念是JavaScript的基本概念,如果您想研究更高级的主题,则很重要。 希望您对JavaScript Scope及其周围的事物有更好的了解。 如果只是没有点击,请在下面的评论中提问。

Scope up your code and till then, Happy Coding!

整理您的代码,然后编码快乐!

翻译自: https://scotch.io/tutorials/understanding-scope-in-javascript

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值