zoukankan      html  css  js  c++  java
  • 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);
    }
    }
    
    });
    

      输出的内容:

  • 相关阅读:
    openwrt 更改 debug 等级(hostapd)
    openwrt 中procd
    openwrt增加串口登录需要密码
    openwrt设置语言的过程
    小程序感悟123
    如何用php实现分页效果
    如何利用h5将视频设置为背景
    关于js中定时器的返回值问题
    canvas二:绘制圆和其他曲线
    canvas一:基本认识
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/5898355.html
Copyright © 2011-2022 走看看