javascript语法小杂杂

1. 变量提升/声明提升

省略var 操作符即未声明变量,会创建一个全局变量(成为global的属性。给未经声明的变量赋值在严格模式下会导致抛出ReferenceError 错误)。
声明变量在任意代码执行前创建,未声明变量直到赋值时才存在。变量声明,不管在哪里发生(声明),都会在任意代码执行前处理。
使用var声明的变量会有变量提升机制,let没有。变量提升看一看老廖的教程。
函数定义不仅提升了函数名,也提升了真正的函数定义。函数定义提升仅仅作用于函数定义,而不是函数表达式。函数表达式可以看作变量,变量提升如果不赋值只是undefined。

2. 作用域

在JavaScript中,一个变量名进入作用域的方式有 4 种:

Language-defined:所有的作用域默认都会给出 this 和 arguments 两个变量名(global没有arguments);
Formal parameters(形参):函数有形参,形参会添加到函数的作用域中;
Function declarations(函数声明):如 function foo() {};
Variable declarations(变量声明):如 var foo,包括函数表达式。

而变量的解析顺序(优先级),与变量进入作用域的4种方式的顺序一致。

一个作用域的例子:
泡泡1是全局作用域,有标识符foo;
泡泡2是作用域foo,有标识符a,bar,b;
泡泡3是作用域bar,仅有标识符c。

javascript语法小杂杂_第1张图片
f6b1c126-da62-11e5-8a20-023c7005156c.png

一般来说语言的Scope分为Lexical Scope和Dynamic Scope。

JavaScript采用Lexical Scope! 我们仅仅通过查看代码,就可以确定各个变量到底指代哪个值。另外,变量的查找是从里往外的,直到最顶层(全局作用域),并且一旦找到,即停止向上查找。所以内层的变量可以shadow外层的同名变量。JS有eval和with两种机制可以改变scope,但两者都会导致代码性能差。JavaScript没有Dynamic Scope。JS中的this机制跟Dynamic Scope很像,都是运行时绑定。

JS没有Block Scope。除了Global Scope,只有function可以创建新作用域(Function Scope)。 不过这已经是老黄历了,ES6引入了Block Scope。

3. this

当函数被调用,一个activation record(即 execution context)被创建。这个record包涵信息:函数在哪调用(call-stack),函数怎么调用的,参数等等。record的一个属性就是this,指向函数执行期间的this对象。

this不是author-time binding,而是 runtime binding。
this的上下文基于函数调用的情况。和函数在哪定义无关,而和函数怎么调用有关。

在箭头函数中,this由词法/静态作用域设置(set lexically)。它被设置为包含它的execution context的this,并且不再被调用方式影响(call/apply/bind),简单点说就是定义的时候所在的this。
如果在 DOM event handler中, this自动设置为触发事件的dom元素。

call/apply/bind
当用call和apply而传进去作为this的不是对象时,将会调用内置的ToObject操作转换成对象。所以4将会装换成new Number(4),而null/undefined由于无法转换成对象,全局对象将作为this。

【我的补充】记住this一般指向的是一个对象(object)!

http://harttle.com/2015/08/14/event-and-this.html
http://imweb.io/topic/56d4763e0848801a4ba198d9
https://github.com/zhengweikeng/blog/issues/11

this作为函数内/对象内的作用指向区别一下。

REF:
深入理解JS中声明提升、作用域(链)和this关键字
MDN变量提升
关于函数传参和变量提升的问题

JS 只有单一的数字类型,内部表示为64位的浮点数,没有分离出整数类型。1 和 1.0 是相同的值。

你可能感兴趣的:(javascript语法小杂杂)