JavaScript学习记录

      什么是作用域,你可以理解为你所声明变量的可用范围,我在某个范围内申明了一个变量,且这个变量能在这个范围内可用, 那么我可以说此范围就是该变量的作用域。

     作用域一般分为局部作用域全局作用域。

在函数体内,局部变量的优先级高于同名的全局变量(函数形参也是局部变量)

作用域链,当我们需要某个变量的值时,我们先去理它最近的作用域去找,如果找不到,就找它的上级作用域,依次类推,直到找到全局,如果全都未定义,那就抛出一个错误。

js中变量的作用域链与定义时的环境有关,与执行时无关。

this指向与申明无关,永远指向距离自己最近最终调用者。

针对函数调用,我们在一个函数内申明this,我们去看它最终是被谁调用,如果最终的调用前啥都没有,this就会指向window,这里只是针对js非严格模式。

 func.call(context,a,b)这一种,如果你传的 context null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context undefined

      obj.method ==> obj.method.call(obj,a,b)

我在上面说,构造函数this会指向new之后的实例(复制出来的副本),但如果在函数里有returnthis指向可能会发生变化。

在构造函数中return 一个对象时,this会指向这个对象,但如果return的不是一个对象,那就不会改变this指向,还是指向new 出来的实例。

https://images2018.cnblogs.com/blog/1213309/201804/1213309-20180418172212011-154519188.png

pushunshift分别为尾部和头部添加元素,popshift分别为尾部和头部删除元素。pushunshift返回的是修改后的数组lengthpopshift返回的是被删除的元素。

JSON.stringify()的作用是将 JavaScript 对象转换为 JSON 字符串,JSON.parse()可以将JSON字符串转为一个对象。

在使用JSON.parse()需要注意一点,由于此方法是将JSON字符串转换成对象,所以你的字符串必须符合JSON格式,即键值都必须使用双引号包裹。

localStorage/sessionStorage默认只能存储字符串,而实际开发中,我们往往需要存储的数据多为对象类型,那么这里我们就可以在存储时利用json.stringify()将对象转为字符串,而在取缓存时,只需配合json.parse()转回对象即可。

在《JavaScript模式》这本书中,new的过程说的比较直白,当我们new一个构造器,主要有三步:

创建一个空对象,将它的引用赋给 this,继承函数的原型。
通过 this 将属性和方法添加至这个对象
最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)

全局对象window上预定义了大量的方法和属性,我们在全局环境的任意处都能直接访问这些属性方法,同时window对象还是var声明的全局变量的载体。我们通过var创建的全局对象,都可以通过window直接访问。

函数执行上下文可存在无数个,每当一个函数被调用时都会创建一个函数上下文;需要注意的是,同一个函数被多次调用,都会创建一个新的上下文

执行上下文栈(下文简称执行栈)也叫调用栈,执行栈用于存储代码执行期间创建的所有上下文,具有LIFOLast In First Out后进先出,也就是先进后出)的特性。

JS代码首次运行,都会先创建一个全局执行上下文并压入到执行栈中,之后每当有函数被调用,都会创建一个新的函数执行上下文并压入栈内;由于执行栈LIFO的特性,所以可以理解为,JS代码执行完毕前在执行栈底部永远有个全局执行上下文。

其中环境记录用于存储当前环境中的变量和函数声明的实际位置;外部环境引入记录很好理解,它用于保存自身环境可以访问的其它外部环境。

全局词法环境组件:

对外部环境的引入记录为null,因为它本身就是最外层环境,除此之外它还记录了当前环境下的所有属性、方法位置。

函数词法环境组件:

包含了用户在函数中定义的所有属性方法外,还包含了一个arguments对象。函数词法环境的外部环境引入可以是全局环境,也可以是其它函数环境,这个根据实际代码而来。

ES6中唯一的区别在于词法环境用于存储函数声明与let const声明的变量,而变量环境仅仅存储var声明的变量

函数声明与var声明的变量在创建阶段已经被赋予了一个值,var声明被设置为了undefined,函数被设置为了自身函数,而let  const被设置为未初始化。

以全局变量和局部变量来说,函数中的局部变量在函数执行结束后这些变量已经不再被需要,所以垃圾回收器会识别并释放它们。而对于全局变量,垃圾回收器很难判断这些变量什么时候才不被需要,所以尽量少使用全局变量。

所谓闭包其实就是一个自带了执行环境(由外层函数提供,即便外层函数销毁依旧可以访问)的特殊函数。

百度百科:

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成定义在一个函数内部的函数

JavaScript高级编程指南》:

闭包是指有权访问另外一个函数作用域中的变量的函数。

MDN(几年前的解释,现已更新):

闭包是指那些能够访问自由变量的函数。自由变量是指在函数中使用的,但既不是函数arguments参数也不是函数局部变量的变量。闭包是由函数以及创建该函数的词法环境组合而成,这个环境包含了这个闭包创建时所能访问的所有局部变量。

函数作用域在定义时就已经确定了,而不是调用时确定。

this默认绑定我们可以理解为函数调用时无任何调用前缀的情景。

如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上,如果函数调用前存在多个对象,this指向距离调用自己最近的对象。

当访问一个变量时,解释器会先在当前作用域查找标识符,如果没有找到就去父作用域找,作用域链顶端是全局对象window,如果window都没有这个变量则报错。

当在对象上访问某属性时,首选i会查找当前对象,如果没有就顺着原型链往上找,原型链顶端是null,如果全程都没找到则返一个undefined,而不是报错。

使用call之类的方法改变this指向时,指向参数提供的是null或者undefined,那么 this 将指向全局对象。

1.callapplybind都用于改变this绑定,但callapply在改变this指向的同时还会执行函数,而bind在改变this后是返回一个全新的boundFcuntion绑定函数,这也是为什么上方例子中bind后还加了一对括号 ()的原因。

2.bind属于硬绑定,返回的 boundFunction this 指向无法再次通过bindapply call 修改;callapply的绑定只适用当前调用,调用完就没了,下次要用还得再次绑。

3.callapply功能完全相同,唯一不同的是call方法传递函数调用形参是以散列形式,而apply方法的形参是一个数组。在传参的情况下,call的性能要高于apply,因为apply在执行时还要多一步解析数组。

箭头函数中没有this箭头函数的this指向取决于外层作用域中的this,外层作用域或函数的this指向谁,箭头函数中的this便指向谁。箭头函数this还有一个特性,那就是一旦箭头函数的this绑定成功,也无法被再次修改。

所有的对象都有__proto__属性,但只有函数拥有prototype属性。

当实例访问某个属性时,会先查找自己有没有,如果没有就通过__proto__访问自己构造函数的prototype有没有,前面说构造函数的原型是一个对象,如果原型对象也没有,就继续顺着构造函数prototype中的__proto__继续查找到构造函数Object()的原型,再看有没有,如果还没有,就返回undefined,因为再往上就是null了,这个过程就是我们熟知的原型链,说的再准确点,就是__proto__访问过程构成了原型链。

https://img2018.cnblogs.com/blog/1213309/202002/1213309-20200217135453434-231361341.jpg

原型就是一个包含了诸多属性方法的对象,原型对象的__proto__指向构造函数Object()的原型。当一个对象访问某个属性时,它会先查找自己有没有,如果没有就顺着__proto__往上查找创建自己构造函数的原型有没有,这个过程就是原型链,原型链的顶端是null

函数均为被普通调用和new调用,所以你可以说函数都是构造函数,也正因如此,ES6才推出了Class类,算是给了构造函数一个真正的名分。

prototype是原型对象,__proto__是访问器属性,对象就是通过这个家伙访问构造函数的原型对象。

var obj = {

    name: undefined

};

console.log('name' in obj);//true

console.log('age' in obj);//false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值