zoukankan      html  css  js  c++  java
  • 你不知道的javascript(上卷)----读书笔记

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title>你不知道的javascript(上卷)</title>
    </head>
    
    <body>
        <script type="text/javascript">
    
        /*
         //9、this 的全面解析
         this的绑定和函数声明位置没有任何关系,之取决于函数的调用方式
         在理解this的绑定过程之前,首先理解调用位置:调用位置就是在代码中被调用的位置(问不是声明位置,)。只有仔细分析调用位置才能回答这个问题:这个this到底引用的是什么
    
         通常来说,寻找调用位置就是寻找“函数被调用的位置”
    
         2.1、函数调用位置
        function baz(){
          console.log("baz");  
          bar();  //bar的调用位置
        }
    
        function bar(){
           console.log("bar");
           foo();//foo的调用位置
        }
        function foo(){
          console.log("foo");
        }
    
        baz();//baz的调用位置
    
         b、函数调用位置2
        function foo(){
          console.log(this.a);
        }
        var a = 2;//2
        foo();
        function foo(){
          "use strict";
          console.log(this.a);  //报错,严格模式下,this不会默认绑定给window
        }
    
        var a = 2;
    
        foo();
    
        function foo(){
          console.log(this.a);
        }
        var a = 2;
        (function(){
           "use strict";
           foo(); //2
        })();
    
        //三种情况下,只要函数执行不是执行在严格模式下,默认绑定才会绑定到全局上
        2.2、绑定规则
    
        2.2.1默认绑定
        function foo(){
           console.log(this.a);
        }
        var a = 2;
        foo();//2
        //非严格模式下,this默认绑定在window下
         
         function foo(){
          "use strict";
           console.log(this.a);
        }
        var a = 2;
        foo();// this is not defined;
        //严格模式下不能将全局对象默认绑定,因此this会绑定到undefined上
    
        function foo(){
            console.log(this.a);
        }
        var  a = 2;
        (function(){
          "use strict";
          foo();//2 
        })()
    
        //严格模式下的调用不影响默认绑定
    
        2.2.2隐式绑定
        function foo(){
            console.log(this.a);
        }
        var obj = {
             a : 2,
             foo : foo
        }
    
        obj.foo();
    
        //无论是直接在obj中定义还是先定义在添加为引用属性,这个函数严格来说不属于obj对象,
        //调用位置会使得obj上下文来引用函数,因此你可以说函数被调用时obj对象“拥有”或者“包含”函数
    
        function foo(){
         console.log(this.a);
        }
    
        var obj2 = {
            a : 42,
            foo : foo
        }
        var obj1 = {
             a : 2,
             obj2 : obj2
        }
    
        obj1.obj2.foo();//42
        //对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。
    
        //隐式丢失
        function foo(){
          console.log(this.a);
        }
        var obj = {
           a : 2,
           foo : foo
        }
        var bar = obj.foo;//函数别名
        var a = "oops,global";
        bar();//"oops,global";
        
    
        2.2.3显示绑定
    
        function foo(){
            console.log(this.a);
        }
        var obj = {
          a : 2,
        }
        foo.call(obj);//2
        //通过foo.call(..),我们可以调用foo时强制把他的this绑定到obj上
    
        //硬绑定 
        function foo(){
            console.log(this.a);
        }
        var obj = {
             a : 2,
        }
        
        var bar = function(){
               foo.call(obj);
        }
    
        bar();//2
        setTimeout(bar,1000);//2
        bar.call(window);//2
        //硬绑定的bar不可能在修改他的this
        //创建函数bar(),并且在内部手动调用foo.call(obj),
        //因此强制把foo的this绑定到obj,无论后面我们如何调用到bar(),
        //他总会手动在obj上调用foo,这种绑定是一种显性绑定,因此我们称之为硬绑定
       
    
       //API调用的‘上下文’
    
    
    
        
       function foo(el){
           console.log(el,this.id); //1 awesome 2 awesome 3 awesome
       }
       var obj = {
           id : "awesome",
       }
       //调用foo()时把this绑定到obj
       var arr = [1,2,3].forEach(foo,obj);
       //console.log(arr);
        
    
        new 绑定
        使用new调用函数,会执行以下操作
        1、创建(或者说构造)一个全新的对象
        2、这个新对象会被执行[[Protoptye]]连接
        3、这个新的对象会绑定到函数调用的this
        4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新的对象
    
        function foo(a){
             this.a = a;
        }
        var bar = new foo(2);
        console.log(bar.a);
    
        2.3优先级
        默认绑定 < 隐式绑定 < 显式绑定 < new 
        .
        .
        .
        .
    
       2.4被忽略的this
       function foo(){
         console.log(this.a);
       }
       var a = 2;
       foo.call(null);//2
       //call 参数为null或者undefined的时候会默认是全局this
    
        柯里化。。。。
    
    
    
        */
    
    
    
    
        /*
          8、this词法 
    	    var foo = a =>{  
    	    	console.log(a);
    	    }
    	    foo(2); //2
    
         //箭头函数,是根据为层(函数或者全局)作用域来决定this
    
    
    	    var foo1 = function(a){
    	    	console.log(a);
    	    }
    	    foo1(2);
    	    // 两种声明是等效的
    
    
    	    var obj = {
    	    	id : "awesome",
    	    	cool:function coolFn(){
    	    		console.log(this.id)
    	    	}
    	    };
    	    var id = "not awesome";
    
    	    obj.cool(); //awesome
    
    	    setTimeout(obj.cool,100); // not awesome 
    	    // setTimeout 导致 cool()函数丢失了同this之间的绑定
    
    	    //解决方案
    	    var obj = {
    	    	count : 0,
    	    	cool: function coolFn(){
    	    		var self = this;
    	    		if(self.count<1){
    	    			setTimeout(function timer(){
    	    				self.count++;
    	    				console.log("awesome");
    	    			},100);
    	    		}
    	    	}
    	    }
    	    obj.cool(); // awesome
        */
    
        /*
    
    
         //7、动态作用域
        function foo(){
        	console.log(a);
        }
        function bar(){
        	var a = 3;
        	foo();
        }
        var a = 2;
        bar();  //2  输出结果是2,词法作用域让foo()中的a通过RHS引用到了全局
                //作用域中的a,因此会输出2
       function foo(){
        	console.log(a); //a is not defined
        }
        function bar(){
        	var a = 3;
        	foo();
        }
        bar();
    
    
        function foo(){
        	var a  = 3;
        	console.log(a); //引用的是局部变量a的值
        }
    
        var a = 1;
        foo();// 3
        */
    
    
    
    
    
        /*
         //5、闭包作用域
         function foo(){
        	var a = 2;
        	function bar(){
        		console.log(a);
        	}
        	return bar;
        }
    
        var baz = foo();
        baz(); //2 foo() 的返回值是bar()函数,所以通过baz()可以执行这个函数
       function foo(){
       	var a = 2;
       	function baz(){
       		console.log(a);
       	}
       	bar(baz);
       } 
    
       function bar(fn){
          	fn();  
       }
    
       foo();//2  foo
        for(var i = 0;i<=5;i++){
        	(function(){
        		var j = i;
        		setTimeout(function time(){
        			console.log(j);  // 每100毫秒输出一个数,分别输出0,1,2,3,4
        		},j*100);
        	})()
        }
        
        for(var i = 0;i<=5;i++){
        	(function(j){
        		setTimeout(function time(){
        			console.log(j); // 每100毫秒输出一个数,分别输出0,1,2,3,4
        		},j*100);
        	})(i)
        }
         for(var i = 1;i<=5;i++){
        	(function(){
        		setTimeout(function time(){
        			console.log(i); // 每100毫秒输出一个数,分别输出6,6,6,6,6
        		},i*100);
        	})()
        }
        */
    
       /*
       //4、提升 --先编译在执行
        a = 2;
        var a;
        console.log(a);//a  因为var声明的变量存在提升
    
        console.log(b); //undefined var声明存在提升,赋值不存在提升,所以b存在但是没赋值
        var b = 2;
        foo();  //函数竟然可以执行,说明函数声明也提升了
        function foo(){
        	console.log(a); //undefined , 声明提升了,不存在赋值提升
        	var a = 2;
        }
        foo(); //1  
        var foo;
        function foo(){
        	console.log(1);
        }
        foo = function(){
        	console.log(2)
        }
         
         //引擎编译如下
        function foo(){
        	console.log(1);
        }
         foo(); //1  
        var foo = function(){
        	console.log(2)
        }
        foo(); //3
        //var foo 尽管出现在在function之前,但是由于是重复声明,所以被忽略掉
        //函数声明会被提升到普通变量之前
        function foo(){
        	console.log(1);
        }
        var foo = function(){
        	console.log(2);
        }
    
        function foo(){
        	console.log(3);
        }
        foo();  // foo is not a function
        var a = true;
        if(a){
        	function foo(){
        		console.log("A");
        	}
        }
        else{
        	function foo(){
        		console.log("B");
        	}
        }
        */
         
    
    
         /*
         //3.4.3、let和var的区别
         for(var i = 0;i<10;i++){
         }
         console.log(i);// 10
    
         for(let j=0;j<10;j++){
         }
         console.log(j);// j is not defined
         //for循环结束后i并没有被销毁,导致全局污染
         */
    
    
         /*
        //3.3.2、立即执行函数:抱在一对括号内
        var a = 2;
        (function foo(){
        	var a = 3;
        	console.log(a); //3
        })();
    
        console.log(a);// 2
         */
    
    
    
          /*
           //块级作用域,函数作用域
           //3.2、规避冲突
          */
          /*
          function foo(){
          	function bar(a){
          		i = 3;
          		console.log(a+i);
          	}
          	for(var i = 0;i<10;i++){
          		bar(i*2);
          	}
          }
    
          foo();//死循环,bar中的i覆盖了for循环中的i导致死循环
          */
    
    
           /*
           //2.2.1、eval
           function foo(str,a){ 
                 eval(str);
                 console.log(a,b); //4
           }
           var b = 2;
           var result = foo("var b = 3;",1);
           console.log("result:",result); //undefined???默认严格模式?
           //书上的结果是1,3因为eval(str)== var  b = 3; 读取的是局部变量3
           function foo(str){
             "use strict";
             eval(str);
             console.log(a);
           }
    
           foo("var a = 2");//a si not defined
           */
    
    
        </script>
    </body>
    
    </html>
    

      

  • 相关阅读:
    Lucene.Net
    关于数据库优化问题总结
    网页幻灯片效果
    ASP.NET邮件发送
    【收藏】悟透JavaScript(李战)
    JS之显示、隐藏控件方法
    初学自定义验证码
    js之判断浏览器类型及版本号
    js清空上传控件的值
    vs2008学习之路
  • 原文地址:https://www.cnblogs.com/SunlikeLWL/p/7376458.html
Copyright © 2011-2022 走看看