JavaScrit全面总结

   前端技术的发展变化太快了,各种各样的框架。再变也离不开js。所以,在此把js的高级语法总结一遍。    js解析和执行包括:全局和函数

一:全局预处理

<script type="text/javascript">
var a=1;
function xx(){
alert(a);
}
</script> 

  这段代码会正常输出a=1;

<script type="text/javascript">
var a=1;
function xx(){
alert(a);
var a=5;
}
</script> 

  输出 undefined   为什么呢?  不报错  输出undefined 。   这就是js的解析执行过程

js执行过程分为:预处理的阶段和执行阶段  

预处理阶段:

一:创建一个词法环境  LexicalEnvironment==window

二:扫描js代码:

1.用声明的方法创建的函数

2.用var   定义的变量

 预处理js处理命名冲突:

先扫描函数声明后扫描变量(var声明)

处理函数声明有冲突会覆盖

处理变量声明有冲突,会忽略

下面为例子:

 <script type="text/javascript">
alert(a);    //undefined
alert(b);  //报错
alert(f);  //字符串的表达式
alert(g);   //undefined

var a=5;
b=6;
alert(b);
function f(){

	console.log('f');
}

//表达式创建的函数 
var g=function(){
console.log('g');

}
alert(g);
 </script>


js分为两个阶段:
一:预处理阶段  1.var  定义的变量   2.声明的方式创建的函数

window
{
   f:指向函数
   a:undefined 
   g:undefined    (表达式创建的函数可以当成变量)

}

二:执行时    没有定义var  就一次性赋值
window
{
    f:输出函数的值
    a:5  变量的定义
    b: 6  函数赋值
    g:指向函数

}

  作用域:

<script type="text/javascript">
alert(a);   //undefined
alert(b);   //undefined
alert(c);   //报错
alert(d);   //报错

 var a=1;
 if (false) {
var b=2; 
 }else{
  c=3;
 }

function f(){
var d=4;
}

for (var i = 0; i <3; i++) {
	
}
alert(i); //输出3

说明:js是没有块作用域的
js是不垮作用域的

  函数作用域:

function f(){
 var x
 function g(){
     //函数  g()是不能访问 var  x的
 }
}

  动态作用域 :   只有在用行时确定

function f(){
    alert(x);
 }
 
 function f1(){
   var x=5;
   f();
 }

  function f2(){
   var x=6 ;
   f();
 }
 f1(); //报错 (等于window  没有全局变量)  说明js 没有动态作用域

  静态作用域  别称:词法作用域 (lexical)   闭包

词法作用域的特点:
一:在js解析器读取创建函数的时候
1.给函数 f 添加一个成员 【【scopel】】 ==创建 函数 f 时的词法环境(lexicalEnv)==window
2.调用 f(); 真正开始执行的时候 创建自己的词法环境 (lexical)==函数本身 f.[[scope]]==window
二:在词法解析解析阶段(在声明的阶段) 确定了相关的作用域

var x=100;
function f(){
    alert(x);
 }
 
 function f1(){
   var x=5;
   f();
 }

  function f2(){
   var x=6 ;
   f();
 }
 f1(); //输出100

  作用域链条:

 function f(){   // 解析  f的 scope==window
 	f  调用时创建自己的词法  (lexical {x=100})-->f.[[scope]]
   var x=100;   
   function g(){  //创建 g时 g.[[scope]]==f.(lexical)
     // g 运行时创建自己的(lexical)-->指向了  g[[score]]

   }
    g();
 }

   形成的链条:

 g.lexical-->g。[[scope]]  -->f.lexical  --->f.[[scope]] --->window

js创建函数的方式:

1.声明的方式 
function f(){


}
2.匿名函数
var f=function(){


}
3.匿名函数
var f=function x(Aargument){


}
4. var f=new Function(“参数”,“alert(xx)函数体”)


function f(){  //给f  scope==window  预处理阶段  把x和g 加进去
	var x=100;
	var g=function(){   //g.score==f.lexical
         alert(x);
	}
	g();
}
f(); //输出100


function f(){  
	var x=100;
	//g.[[scope]]==window
	var g= new Function(“”,“alert(x)”);   
	g();  //报错  x没有定义
}
f(); 

 </script>

  

作用域的本质:
当在函数中找到一个变量的时候,首先,会在这个函数本身的词法环境中去找,找到结束--->找不到,去父函数的词法环境中去找--->window 中途找到退出

具体的用法:(作用域就是一个信息隐藏)

全局变量越来越多时,会导致冲突。

匿名的立即调用函数的写法:
(function(){
 var a=5;
 var b=6;
 function f(){
   alert(a);

 }
 window.f=f;  //技巧:在外面能访问到  定义window

})();
f();  //输出5
这样就只对外面提供了一个f函数,减少了命名的冲突

  闭包:

定义:是词法闭包的简称,引用了自由变量的函数,这个被引用的自由变量将和这个函数一同存在。即使离开了他的创建环境也不例外。(闭包就是一个对象,里面包含的一个函数,函数中有被他补货的变量)

本质:js支持作用链和函数的嵌套函数

自由变量指父函数的自由变量(a,b)

闭包是什么时候创建的呢:

1.给f2创建一个[[scope]],===父函数f1的词法环境

2.扫描f2的代码,保留f1的词法环境 

闭包函数的写法:

如何查看(在浏览器中):

代码:

<script type="text/javascript">

function f1(){   //父函数
	var a=10;
	var b=20;
	function f2(){  //子函数
		coonsole.log(a);
	}
	f2();  
}
f1();

//即使离开了他的创建环境也不例外。
function f1(){
	var a=10;
	var b=20;
	return function f2(){
	coonsole.log(a);
	}
}
var result=f1();
result();
</script>

  不调用父元素的属性是不会产生闭包的。

代码:

function f1(){
 	var m=10;
 	function f2(){

 		coonsole.log("fss");
 	}
 	f2();
 }
 f1();

  不会看到任何结果:

 

调用父的父元素:(是可以产生闭包的)

function f1(){
 var m=10;
    function f2(){
    	var n=20;
    
    function f3(){
    	coonsole.log(m);
    }
    f3();
   }
   f2();
 }

  效果:

使用闭包的优势:

1.减少全局变量

 function add(){
 	var a=0;
 	return function(){
 		a++; 
 		alert(a);
 	}
 }
 var result=f();
 resul ();
 resul ();

2.减少传递给函数的参数数量

 //减少参数
function add(base,max){

}
//构建一个计算工厂的函数
function calFactory(base){
	return function(max){
       var total=0;
     for (var i =   1; i <=max; i++) {
     	total+=i;
     }
     return total+base; 
	}
}

var adder=calFactory(2);
alert(adder(3));   //输出8;
alert(4);  //输出12

var adder2=calFactory(1);
alert (adder2(3));  //输出7


function calFactory(base){
  return function (max){
  	var total=0;
  	for (var i = 1 ; i <=max; i++) {
  		total+=i;
  	}
  	return total+base;

  }
}

3.封装

//立即调用的函数
(function(){
var m=0;
function getM(){
	return m;
}
funciton setM(){
	m=val;
}
window.g=getM;
window.f3()=setM;
})();

f(12);
alert(g());  //输出12

  

闭包的注意点:

一:对捕获的变量只是个引用,不是复制

function f(){
 	var num=1;

 	 function g(){
        alert(num);
 	 }
 	 num++;
 	 g();
 }
f();   //输出2

  

//分析:
1.f调用生成一个f 的词法环境 le==g的[[scope]] 产生闭包 g函数没有真正的运行 num++;
2.f的词法环境是一个对象 (num就是一个成员) num的值就是f函数的词法环境
3.g的[[scope]]==f 的 le==num
所以就是对象的引用

二:父函数每调用一次,会产生不同的闭包

 function f(){
 	var num=1;
 	return function(){
 		num++;
 		alert(num);
 	}
 }
 var result1=f();
 result1();//2
 result1();//3

 var result2=f();
 result2();//2
 result2(); //3

 分析:
 1.调用两次不同的 f() 就创建了不同的词法环境
 所以:父函数没调用一次就会产生不同的闭包

  三:循环中的问题

<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>

<script type="text/javascript">
for (var i = 1;i <=3; i++) {
	var ele=document.getElementById(i);
	ele.onclick=function(){
		alert(i);
	}
}
//点击一直输出4

//解决方案  闭包  用匿名函数
for (var i = 1;i <=3; i++) {
	var ele=document.getElementById(i);
	ele.onclick= (function(id){
return function(){
		alert(id);
	}
  })(i); 
}

对象的种类:

1. undefined

2.null

3.string

4.number

5.boolean 

对象的类型:

1.js内置的

2.宿主环境(window)

3.自己创建

  对象的创建:

1.对象自变量的创建

<script type="text/javascript">
var p={
     name:“sunliyuan”,
     work:function(){
     	console.log("working...");
     },

     _age:18,
     get age(){
       
     return this._aga;

     },

     set age(val){
     	if(val<0||val>150){
      throw new Error("invalid value");
     	}else{
     		this._aga=val;
     	}
     },
     address:
};

console.log(p.name);

</script>

  

又一访问种方式:

括号的访问:

 

级联访问实例:

 通过Object对象:

自己给自己加上属性:

 

另一种加法:

 

还是100(不可修改)

//get,set,writable,enuerable,configurable,value
Object.definePropertis(p,{
salary:{
      value:1000,
      writable:false
},
gender:{
	value:true
},
height:{
get:function(){
	return 180
},
set:function(val){
	console.log(val);
}
}

});

  输出的内容:

原文地址:https://www.cnblogs.com/sunliyuan/p/5898355.html