zoukankan      html  css  js  c++  java
  • 你不知道的javaScript笔记(2)

    this和对象原型

    this是一个很特别的关键字,被自动定义在所有函数的作用域中

    // foo.count 0,字面理解是错误的

              function foo(num) {
                  console.log("foo:"+ num);
                  this.count++;
              }
              foo.count = 0;
              var i;
              for(i=0;i<10;i++){
                  if(i>5){
                      foo(i)
                  }
              }
              console.log(foo.count)  //0

     // 使用词法作用域解决问题

            function foo(num) {
                console.log("foo:"+ num);
                data.count++;
            }    
    
            var data = {
                  count:0
            };
            var i;
            for(i=0;i<10;i++){
                if(i>5){
                    foo(i)
                }
            }
            console.log(data.count);  // 4

    // foo标识符来替代this来引用函数对象,回避了this 的问题,完全依赖于变量foo的词法作用域。

            function foo(num) {
                console.log("foo:"+ num);
                foo.count++;
            }
            foo.count = 0
            var i;
            for(i=0;i<10;i++){
                if(i>5){
                    foo(i)
                }
            }
            console.log(foo.count) //4

        //强制this 指向foo函数对象

            function foo(num) {
                  console.log("foo:"+num);
                  this.count++
             }
             foo.count = 0;
             var i;
             for(i=0; i< 10; i++){
                  if(i>5){
                      foo.call(foo,i);
                  }
             }
            console.log(foo.count)  //4

    this是在运行是 绑定的,并不是在编写时绑定的,它的上下文取决于函数调用时的各种条件,this的绑定和和函数声明的位置没有任何关系,只取决于函数调用的方式。

    this全面解析

    调用栈与调用位置

            function baz(){
                //当前调用栈是:baz
                // 因此,当前的调用中位置是全局作用域
                console.log("baz");
                bar(); // <--bar的调用位置
            }
            function bar(){
              //当前的调用栈是: baz-> bar
              // 因此,当前调用位置在baz
              console.log("bar);
              foo(); // <-- foo 的调用位置
            }
    
            function foo(){
              //当前的调用栈是: baz-> bar->foo
              // 因此,当前调用位置在bar
              console.log("foo");
            }
            baz(); // <-- baz 的调用位置

    只有运行在非strict mode 下,默认绑定才能绑定到全局对象。

    对象属性引用链中只有最顶层或者说最后一层灰影响调用位置。

            function foo() {
              console.log(this.a);
    
            }
    
            var obj2 = {
                a: 42,
                foo:foo
            };
    
            var obj1 = {
                a:2,
                obj2: obj2
            };
    
            obj1.obj2.foo(); // 42

    硬绑定的典型应用场景就是创建一个包裹函数,传入所有的函数并返回接收到的所有的值。

              function foo(something){
                  console.log(this.a,something);
                  return this.a + something;
              };
    
              var obj = {
                  a:2
              };
    
              var bar = function() {
                return foo.apply(obj,arguments);
              };
    
              var b = bar(3) ; // 2 3
              console.log(b)  // 5

    另一种方法是创建一个i可以重复使用的辅助函数

              function foo(something){
                  console.log(this.a, something);
                  return this.a + something;
              }
    
              // 简单的辅助绑定函数
              function bind(fn,obj){
                return function(){
                  return fn.apply(obj,arguments);
                };
              }
    
              var obj = {
                 a:2
              }
    
              var bar = bind(foo,obj);
              var b = bar(3); // 2 3
              console.log(b) // 5

    ES5 中提供了内置的方法 Function.prototype.bind,  bind(..) 会返回一个硬编码的新函数,它会

     

    把参数设置为this的上下文并调用原始函数。

            function foo(something){
              console.log(this.a, something);
              return this.a + something;
            }
            var obj = {
                a:2
            }
    
            var bar = foo.bind(obj);
            var b = bar(3); // 3 5
            console.log(b) // 5

    API 调用的 上下文

            function foo(el){
              console.log(el,this.id);
           }
           var obj = {  
              id: "awesome'
           }
    
          // 调用 foo(..)时把this 绑定到obj
          [1,2,3].forEach(foo,obj);
          // 1 awesome 2 awesome 3 awesome

    new可以影响函数调用时this 绑定行为的方法。

            function foo(a){
                this.a = a;
             }
           var  bar = new foo(2);
           console.log(bar.a); // 2

    判断this

    1.函数是否在new 中调用(new 绑定)? 如果是的话this 绑定的是新创建的对象。

    var bar = new foo();

    2.函数是否通过call , apply (显示绑定) 或者硬绑定调用? 如果是的话,this的绑定时指定的对象。

    va bar = foo.call(obj2)

    3.函数是否在某个上下文对象中调用(隐式绑定) ? 如果是的话,this 的绑定时在那个上下文。

    var bar = obj1.foo()

    4.如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象上。  

    var bar = foo();

    软绑定

            function foo(){
              console.log("name:" + this.name);
            }
    
            var obj = {name: "obj"},
            obj2 = {name: "obj2"},
            obj3 = {name: "obj3"},
            obj3 = {name: "obj3"};
    
            var foo0BJ = foo.softBind(obj);
            foo0BJ();  // name:obj
            obj2.foo = foo.softBind(obj);
    
            obj2.foo(); // name:obj3 <--看!
            setTimeout(obj2.foo,10);
            // name:obj <--- 应用了软绑定

     

  • 相关阅读:
    python中的反射
    ZOJ 3827 Information Entropy 水
    我的软考之路(七)——数据结构与算法(5)之查找
    nginx.conf 集群完整配置
    恼人的函数指针(二)
    C语言100个经典的算法
    spring事务心得积累
    Vue报错:OPTIONS 405 Method Not Allowed以及CORS跨域错误
    IDA脚本dump内存的示例
    lightProxy
  • 原文地址:https://www.cnblogs.com/nmxs/p/7090666.html
Copyright © 2011-2022 走看看