Some knowledge of js variable declaration confusing

This is some of the confusing places I encountered during my JavaScript learning process. I took advantage of the time to sort it out.

variable promotion

Variable and function name escalation precedence

There are variables in the js scope, which is easy to understand, but there are some details to pay attention to.

console.log(foo);  // 函数
function foo(){
    console.log("函数声明");
}
console.log(foo); // 函数
var foo = "变量";
console.log(foo); // 变量

When the variable name has the same name as the function name, and both are promoted, which declaration is the final result?

There are two knowledge points:

  1. var foo; does not overwrite the previous variable
  2. Function promotion has higher priority than variable promotion, and will not be overridden by variable declarations, but will be overridden by variable assignments, so the above code is actually
function foo(){ // 优先级最高,提升到最前面
    console.log("函数声明");
}
var foo; // 只提升声明,不提升赋值,且不能覆盖函数声明
console.log(foo); 
console.log(foo); 
foo = "变量"; // 可以覆盖函数声明
console.log(foo); 

Variable hoisting for even-equal assignment

var num1 = 1;  
function   fn(num3){  
    console.log(num1);    //output    undefined  
    console.log(num3);    //output  4  
    console.log(num4);    //throw error  “num4 is not defined”  
    console.log(num2);    //throw error  “num2 is not defined”  
    var num1 = num4 = 2;  // js 连等赋值  num4 不会被提升
    num2 = 3;             // 没有 var 会挂载到全局作用域,但不会提升,所以之前会报错
    var num3= 5;  
}  
fn(4);

If judgment inner variable promotion

if (true) {  
    function fn(){ return 1; }  
}else {  
     if(false){  
       function fn(){ return 2; }  
     }  
}  
console.log(fn.toString()); 
console.log(fn())

Here is an excerpt from the original text where this example was found:

Both chrome and ie are function fn(){ return 2;}, but firefox still reports an error.
It can be seen that the three treatments are not the same. Variable declarations are advanced in ff, but function declarations in block scope are not. Under chrome and ie, the function declaration in the block-level scope will be advanced in advance, and the subsequent declaration will overwrite the previous declaration.

As I write this, the test results for IE10 and below, return 2, and IE11 and Google, newer versions of Firefox, return 1

var fn;
console.log(fn); // undefined

if (true) {  
    function fn(){ return 1; }  
}else {  
     if(false){  
       function fn(){ return 2; }  
     }  
}  
console.log(fn.toString());  // 函数 1
console.log(fn()) // 1

if judges that the inner function is not improved

Assign a value to a named function

function test5() {
  var fn = function fn1() {
    log(fn === fn1); // true
    log(fn == fn1); // true
  }
  fn();
  log(fn === fn1); // fn1 is not defined
  log(fn == fn1);  // fn1 is not defined
}
test5();

Inside the function, fn is exactly equal to fn1

Outside the function, fn1 is not defined

!compatible

b(); 
var a = function b() {alert('this is b')}; 

It is possible to execute b in ie8 and below browsers. It shows that different browsers have differences in the details of processing function expressions.

hoisting of declarations after return

Variables after function return statement, function declaration promotion

function text6() {
   var a = 1;
   function b() {
     a = 10;
      return;
      function a() {}
    }
    b();
    console.log(a);  // 1
}
text6();

Assignment within the scope of a function

In js, when it comes to variable assignment, we must first talk about scope, and scope, before es6, only functions can form independent scopes, and then the nesting of functions forms the scope chain of js. Elements in the parent scope can be accessed from the child scope. The scope of a function is determined when the function is determined, regardless of the call.

// test1
var x = 1;
function foo(x) {
  var x = 3;
  var y = function() { 
    x = 2;
    console.log(x)
  }
  y();
  console.log(x);
  return y
}
var z = foo() // 2 2
z() // 2

This function will output three 2s, pointing to the same x, or even changing x to an object, it is more obvious

// test2
var x = "abc";
function foo(x) {
  var x = c;
  var y = function() { 
    return x;
  }
  return y;
}
var c = {a:1}
var z = foo(); 
var b = z();
console.log(b === c); // true

In the above example, after the foo function is executed, it returns the y function and assigns it to z, and z points to the y function (function body). At this time, z is not in the scope of the foo function, and x cannot be accessed in this scope, but z only A pointer to reference type data, just pointing to the same object as x. When the z function is executed, the value of x will be returned. This value is the value of x accessed in the scope of the function y. .

But at the same time, it should be noted that although the function scope is determined when the function is written, the specific value is related to the timing of the call.

// test3
var x = "abc";
function foo(x) {
  var x = c;
  var y = function() {
    x.a++;
    return x;
  }
  return y
}
var c = {a:1}
var z = foo(); 
console.log(z()) // {a: 2}
console.log(z()) // {a: 3}
console.log(z()) // {a: 4}

In this example, the same object is output three times, but the output value is different. This is because the output value is different, which is related to the actual value when calling.

At the same time, another value of the function is also related to the calling of the function, which is this. A function's this points to the caller of the function, regardless of where the function is defined.

var x = "abc";
var b = {x:"def"}
function foo(x) {
  var x = c;
  var y = function() {
    x.a++;
    return this.x;
  }
  console.log(y()); // abc
  return y
}
var c = {a:1}
var z = foo(); 
console.log(z()) // abc
b.a = z;
console.log(b.a()) // def
b.b = {
    x: "hig",
    z: z
}
console.log(b);
console.log(b.b.z()); // hig

The above example shows that this in the function always points to the object that calls the function this time. If not, it points to the global object, and if the pointed object itself is a property of another object, this does not affect, even, it will be on In this example, the x attribute of bb is deleted. When the last call is made, the this of bbz() still points to the object pointed to by bb. Even if the object has no x value, it will return undefined instead of looking for it from the superior.

function fn(){
    var array=[];
    var b = {a:1}
    for(var i=0;i<10;i++){
        array[i]=function(){
            var abc = {def: "ghi"};
            return b;
        }
    }
    return array;
}
var a = fn();
console.log(a) //[ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
console.log(a[0].toString()) //f
console.log(a[1] === a[2]) // false
console.log(a[1] == a[2]) // false
console.log(a[1].toString() === a[2].toString()) // true
console.log(a[1]() === a[2]()) // true

Comparison of equality of two functions: the scope of the two functions is the same and the content of the function is the same, then the result of the comparison is that the two functions are equal, otherwise, they are not equal! We don't use == to compare directly, but to compare according to this rule.

Functions are objects, composite values. Generally comparing references, the same reference is equal; otherwise, it is not equal. Comparing toString makes little sense: because scope is just an invisible transparent rule for function calls

assign value to arguments

function fn(a, b) {
    var a = 1;
    var b = 2;
    console.log(arguments[0]);
    console.log(arguments[1]);
    arguments[0] = 3;
    arguments[1] = 4;
    console.log(a);
    console.log(b);
}

fn(5,6) // 1 2 3 4 传入实参,实参和形参指向相同
fn() // unde unde 1 2 没有传入实参,arguments 指向 undefined,形参与实参不再相关
function fn(a, b) {
    'use strict'
    var a = 1;
    var b = 2;
    console.log(arguments[0]);
    console.log(arguments[1]);
    arguments[0] = 3;
    arguments[1] = 4;
    console.log(a);
    console.log(b);
}

fn(5,6) // 5 6 1 2 严格模式下 arguments 指向实参,与形参不相关
fn() // unde unde 1 2

The Arguments object in javascript is the actual parameter of the function, and the length of the arguments object is determined by the number of actual parameters rather than the number of formal parameters. Formal parameters are variables that are re-opened within the function to store the memory space, but they do not overlap with the memory space of the arguments object.

In the non-strict mode under the es5 specification, the actual parameters are passed in when the function is called, the formal parameters used inside the function point to the same, the specific properties of arguments change, and the value of the formal parameters will also change, but if no actual parameters are passed in, the arguments It has nothing to do with the point of the formal parameter.

In the strict mode of the es5 specification, the formal participation arguments are stored separately and will not be related

But since es6, the effect in non-strict mode is the same as es5 strict mode, that is, arguments and parameter symbols are stored separately.

In the strict mode of es6, modifying the arguments will report an error.

The problem of the same name of parameters, variables and functions in functions

function aa(a,b,c) {
    console.log(arguments); // {0: 函数a, 1: 2, 2: 3} 通过更改形参的值,可以更改 arguments 
    function a(){console.log(a)}
    console.log(a); // 函数 a
    console.log(aa); // undefined, var aa 被提升
    console.log(arguments); // 同上
    var a = "ee";
    var aa = "444";
    arguments = 6;
    console.log(a); // ee
    console.log(aa); // 444
    console.log(arguments) // 6
}
aa(1,2,3)
function aa(a,b,c) {
    'use strict' // 调用严格模式
    console.log(arguments); // 指向arguments 对象,{0:1,1:2,2:3}
    function a(){console.log(a)}
    console.log(a); // 函数a
    console.log(aa); // undefined
    console.log(arguments); // 同上
    var a = "ee";
    var aa = "444";
    arguments[0] = 6;
    // arguments = 6; 严格模式 不能直接对 arguments 进行赋值
    console.log(a); // ee
    console.log(aa); // 444
    console.log(arguments) // // 指向arguments 对象,{0:6,1:2,2:3}
}
aa(1,2,3)

Some explanations found online

The order of filling variables is: function parameter -> function declaration -> variable declaration. When a variable declaration encounters a VO with the same name, it will not affect the existing properties.
Function parameter——The property of a variable object consisting of name and corresponding value is created; if no corresponding parameter is passed, then the property of a variant object consisting of name and undefined value will also be created.
Function declaration ——A property of a variable object consisting of a name and a corresponding value (function-object) is created; if a property with the same name already exists in the transmutation object, the
variable declaration of this property is completely replaced———— A property of a variable object consisting of a name and a corresponding value (undefined) is created; if the variable name is the same as an already declared formal parameter or function, the variable declaration does not interfere with the existing property

Under normal circumstances, it will be parsed in four ways.
Language built-in:
formal parameters:
function declaration:
variable declaration:
there are exceptions:
the built-in name arguments behave strangely, it seems that they should be declared after the formal parameters, but before the declaration . This means that if there are arguments in the parameter, it will take precedence over the built-in one. So try not to use arguments in formal parameters;
defining this variable anywhere will result in a syntax error.
If multiple formal parameters have the same name, the last one has higher priority, even if its value is undefined when actually running;

material:

https://segmentfault.com/q/1010000006727575?_ea=1111028

http://www.cnblogs.com/sharpxiajun/archive/2011/09/16/2179010.html

https://www.cnblogs.com/zhouyongtao/archive/2012/11/22/2783089.html

https://www.cnblogs.com/luqin/p/5164132.html

https://segmentfault.com/q/1010000006135524

https://www.cnblogs.com/Eric1997/p/7499819.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325228982&siteId=291194637