preface

Dart functions, lambdas, lexical scopes, Javascript scopes, scope chains, closures, This, etc.

Video address: portal.

function

The concept of a function is the building blocks of readable, maintainable, and reusable code. A function is a set of statements that perform a specific task. Functions organize programs into logical blocks of code. Once defined, functions can be called to access the code. This makes the code reusable. In addition, functions can easily read and maintain program code.

The function declaration tells the compiler the function name, return type, and parameters. The function definition provides the actual body of the function.

Take a look at the basic function declaration:

Still is the first call after the way, if the first call is an error.

Error: Method not found: ‘action’.

The return value of the function

As with JS functions, functions can return any type of data, but Dart functions have return value type checking that can be turned on. For example, the following way

A function with no return value can be checked with void.

Parameters of a function

A parameter is a mechanism for passing values to a function. Parameters form part of a function’s signature. Parameter values are passed to the function during the call. Unless explicitly specified, the number of values passed to a function must match the number of parameters defined.

Function arguments can be declared in several ways:

  1. Parameters that must be passed

Values must be passed to the desired parameters during a function call.

As you can see above, the action function declares two parameters (parameters), but only one is passed in the function call, because this declaration of function parameters is mandatory, so an error is thrown.

Error: Too few positional arguments: 2 required, 1 given

  1. Parameter location Optional

To specify optional positional arguments, use square brackets []. Modify the above example:

As you can see, when the age argument is enclosed, no errors are reported when the function is called. The default value is null if the optional position argument is not passed

Multiple optional positional parameters are declared as follows

One caveat here: All required arguments in the Dart function must be declared before the optional positional arguments. Be careful.

Optional positional arguments can be given default values:

The default value must be a compile-time constant const, not final, because final is a runtime constant

  1. Optional named parameter

Unlike positional parameters, the parameter name must be specified when the value is passed. Curly brace {} can be used to specify optional naming parameters.

First of all, such declarations are still optional, and can be passed or not.

However, the optional named parameter must be passed with the declared variable name

Optional named parameters can also be declared with default values

Note: Only one of the optional named parameters and location parameters can appear.

  1. Function as argument

Dart supports functions passed as arguments to functions.

Arrow function

If the function contains only one expression, use the arrow method.

=> expr; Syntax is {return expr; The abbreviation of}

One caveat: expressions, not statements, can only appear between the arrow and the semicolon. For example, you can’t put an if statement there, but you can use conditional expressions.

You can see that the arrow function has a return value, of course you can also set the return type of the void function, so that the return value is masked.

Arrow functions are also called Lambda functions, so what is Lambda?

Lambda

A function is a block of code.

In previous versions of Java, you could not assign a function value to a variable. Later, you could, but it looked something like this:

Of course, this is not a very neat way to write it. So, to make this assignment more elegant, we can remove some useless declarations and start the following evolution

Thus, we have successfully assigned a block of code to a variable in a very elegant way. And this piece of code, or this function that is assigned to a variable, is a Lambda expression.

Alas, the anonymous function on the right would be a Lambda if the resulting transformation was called an expression.

Anonymous functions:

Most functions are named, such as main(), print(), etc. We can also create an anonymous function called an anonymous function, sometimes called labmbda or closure. Take a look at the following example

scope

Dart’s function scope is Lexical scope scoping. Is static scope.

No matter where a function is called or how it is called, its lexical scope is determined only by the position at which the function is declared.

Lexical scope is such a static scope model, which consists of global scope function created scope and block scope.

The internal side of a Lexical scoping is able to access variables defined in the external side scoping.

The variable defined in printName is not visible to the variables in main. Dart, like JavaScript, has chained scope, meaning that a child scope can access variables in a parent (or even an ancestor) scope and not vice versa.

As we can see from the above example, synecdosimetry actually exists as a chain. A new scope can be opened in one scope, and variables with same names can be allowed in different scopes. What rules do we use to access a variable in a scope?

In the example above, we can see that the variable A is defined in both main and firstScope. We print in firstScope, prints 2 in firstScope and print in main prints 1 in mainScope.

We can already summarize the rule: the nearest is first.

If you access a variable in a scope, it first looks to see if the variable is already defined in the current scope, and if so, it is used. If the current scope does not find the variable, it looks for it in the scope above it, and so on down to the original scope. If this variable does not exist on any scope chain, Error: Undefined name’ name’ is raised.

Variables in the Dart Scope are statically determined.

We can see that the variable A exists in main’s parent scope and has been assigned a value, but we also define a variable ain main’s scope. If a is not specified within the scope of print, the scope of a is not specified within the scope of print. If a is not specified within the scope of print, the scope of A is not specified within the scope of print. Local variable ‘a’ can’t be referenced before it is declared.

Javascript scopes

Scope in javascript is a long story, but let me break it down:

To clarify a few concepts, there is no block-level scope in javascript, only function scope and global scope. Take a look at the following javascript example:

You can see that a, declared in the if block, can still be accessed outside the block. It is bound to the global scope, where this is the window object. So this.a can print inke.

Dart has block-level scope. Take a look at this example:

You can see that variables declared in the if execution block are not externally accessible.

Dart’s if,while,for, and so on have block-level scopes. As shown above, the parent scope does not have access to variables declared in the child scope.

We can see that es6 has two new things, let and const. These two ways of declaring variables completely replace var. But why did ES6 introduce these two ways of declaring variables?

Variables declared by lets and const are accessed in the current execution block, thus filling in javascript’s lack of block-level scope.

Why didn’t javascript design block-level scopes in the first place?

After reading at least 20 articles, I came closest to the real answer: design defects/bugs

So the first es6 supplement is let, const. And basically we don’t write var.

As we continue to explore, there are only two types of scope in javascript: function scope and global scope. The global scope is needless to say. Let’s focus on the scope of functions.

Scopes

Here I would like to mark some of the following content I really did not find a solid basis, some of the logic is inferred, if there is any mistake, welcome to correct.

Functions in javascript can also create functions inside functions, so scopes are nested layer by layer, and since the nature of scopes is preserved, child scopes can access variables in the parent scope, so a scope chain [[scopes]] is generated, as shown in the following example.

Debug will look at the scope chain as follows:

The Scopes displayed in function C are 3 in length, indicating that there are three Scopes in function C’s scope chain, or four in its own case. Because the breakpoint is inside the B function and is where the C function is called.

Aa, BB, and cc printed inside function C look first at their scope and then up until they find the top-level scope global. Global, for example, is the Window object in a browser.

So you know what a chain of action is, and it’s familiar to you, and I’m sure you memorized it when you first learned about prototype chains, and how it works, it’s actually not that different, and in the next class you’ll learn more about prototypes, inheritance, and so on.

Closure

Function A and function B are (Closure). In the last two Scopes, there are three Scopes in each. In the last Scopes, there are three Scopes in each.

Function C has closures for function A and function B in its scope chain, because function C calls parameters inside function A and function B.

I’m sure some of you are wondering:

I remember that closure is supposed to be a function that covers a function and then returns a function.

All else aside, at least from my example above, I’ve already overruled your conclusion.

Real concept:

The sum of the “function” and the “variables accessible within the function” (also known as the environment) is a closure.

What is the meaning of return? If this closure is not returned, there is no way to call… Only after the return is returned can the internal variables of the function be accessed in the external context.

There is also a myth about closures: memory leaks. I’m sure most people think that the downside of closures is the risk of memory leaks.

Whoever said that has no idea what a memory leak is. A memory leak is when variables that you don’t need (or can’t access) still occupy memory space and can’t be reused.

The variable inside the closure is clearly the variable we need (lives), why is it a memory leak?

How did this rumor originate?

Because Internet explorer. There is a bug in IE, IE is still unable to retrieve variables referenced in closures after we use them.

This is an IE problem, not a closure problem. See this article by Masumi Seto, Portal

Now that IE is fading away, you can refresh your mind.

This

Here are a few tips.

Something we’re familiar with in javascript is called this. What is this? You probably only remember the “this” as a pointing question, because you always ask in front end interviews, right, but we’re not asking the pointing question, we’re asking what “this” is?

This is the scope at which the function is currently executed, as in the example above, this in function C points to the Global scope. Of course, the Global scope is also part of the scopes chain.

We can use apply, call, and bind to change the direction of this, which refers to the direction in the scope chain.

Now, one might ask here, what if I apply a function d? D is not in the original function’s scope chain, so if you use apply to refer this to D, you will have an additional Closure in the scope chain. And point this to the past.

In this case this is the function D.

Dart, by the way, does not have the this keyword.

END

Dart function, Lambda, lexical scope, Javascript scope, scope chain, closure, This, etc.

This series appears to be nearing its end, with 8 or 9 sections planned. Welcome to like and forward.