阴影中的曙光

你不知道的JS

2018.11.07 / 技术相关 / 点击 38 / 回复 0 / JavaScript

没办法啊前端基本上就是看JS能力

作用域

变量出现在赋值操作符左侧时进行LHS查询 e.g. data = 123 寻找物理存储的地址
变量出现在赋值操作符右侧时进行RHS查询 e.g. var some = data 寻找物理存储内的数据

  • 函数逻辑操作应该遵从尽量少引用外部变量,尽量降低函数粒度,尽量减少副作用等原则
  • 以var声明变量的时候实际上是会提升到函数的最顶端对所有变量进行声明,如果声明的同时进行赋值,则会在相应行数再进行变量的赋值.
  • 函数和变量的声明都会提升,但是如果函数和变量占用了同一个变量名,则函数会优先声明.
  • 函数可以在定义时的词法作用域外的地方调用,并且此函数能访问到定义时的词法作用域,就是闭包.因为这个索引函数始终保持这对其定义时词法作用域变量的访问权限,所以垃圾回收机制无法对这个作用域内的变量进行回收,从而形成’内存泄漏’
  • JS作用域遵从词法作用域,及关注函数定义时的位置,而非动态作用域语言中寻找变量参照调用顺序,延调用栈寻找变量

This

This的绑定主要取决于函数的调用栈以及调用位置,调用位置的判断遵循以下四个原则

  • 默认绑定 ,函数在全局作用域调用时,无显示调用关系,则this指向全局对象
  • 隐式绑定,独立声明的函数在以 对象.函数名() 的形式调用时函数内this指向此对象,但是值得注意的是
    function foo() {
        console.log(this.a);    
    }
    var obj = {
        a: 2,
        foo:foo
    };
    var bar = obj.foo;
    var a = "oops,global"
    bar(); //"oops,global"

在 对象.函数名 这种组合做右值的时候其实本质上只是完成了一个函数本身的引用,并不能改变函数内this指向,所以会采用默认绑定,函数传参的本质也是将实参作为右值赋给形参,所以 setTimeout( obj.foo, 100 ) 这类的写法也都是遵从默认绑定规则而不是隐式绑定

  • 显示绑定, call方法和apple方法
  • New 绑定
  • 参数预设
function foo(p1,p2) {
      this.val = p1+p2
}
var bar = foo.bind(null , "p1")
var baz = new bar("p2")
baz.val //p1p2