数据类型
在最新的 ECMAScript 规范中,定义了7种数据类型
- null
- undefined
- boolean
- number
- string
- symbol(不了解)
- object
其中前6种为基础数据类型,只有 object 为引用类型
基础数据类型和引用类型划分的依据是其在内存中存储的形式
基础数据类型在内存对应的位置存储的是null,undefined,字符串,数值或布尔值(symbol)
引用类型在内存对应的位置存储的是地址
通过操作符 typeof 判断数据类型,不过有以下例外
typeof null // 'object'
typeof function(){} // 'function'
通过操作符 instanceof 判断对象的类型
The instanceof operator tests whether the prototype
property of a constructor appears anywhere in the prototype chain of an object.
只要该对象的原型链上有以该构造函数生成的对象,就返回true
[] instanceof Object // true
[] instanceof Array // true
[] instanceof Date // false
函数与对象
typeof function(){} // 'function'
函数也是对象
对象大都是通过函数new出来,不考虑函数对象
var obj = { a: 10, b: 20 }; // 将看成是一种语法糖
// 相当于
var obj = new Object();
obj.a = 10;
obj.b = 20;
var arr = [5, 'x', true];
// 相当于
var arr = new Array();
arr[0] = 5;
arr[1] = 'x';
arr[2] = true;
函数Fn也是对象,具有属性prototype,其指向一个对象P,通过new Fn()产生的对象fn,fn.__proto === Fn.prototype,Fn.prototype === P
Returns a reference to the Object
constructor function that created the instance object.
对象通过 constructor 找到生母是谁
function Fn() { }
let fn = new Fn()
Fn.constructor === Function // true
fn.constructor === Fn // true
.png)
通过 hasOwnPrototype ,判断某属性是对象自身拥有的,还是其原型链上的
函数
内部变量声明&提升
- 函数在执行之前会搜索函数体内所有的函数声明,将其移至函数体的开始
-
函数在执行之前会搜索函数体内所有通过 var 声明的变量,将其移至函数体的开始
- 移至函数声明的后面
- 只声明变量,并不给变量赋值或赋值为undefined,赋值的操作,仍在原地
console.log(Person) // function Person(){}
function Person(){
}
var Person = 2
console.log(Person) // 2
console.log(Person) // function Person(){}
var Person = 2
function Person(){
}
Person // 2
// 相当于
console.log(Person)
function Person(){
}
var Person
Person = 2
参数
var v1 = {}
function func(obj){
obj = {
name: 'v1'
}
}
func(v1)
// 相当于
func(v1)
function func(obj){
let obj = v1
obj = {
name: 'v1'
}
}
函数中传递参数,相当于额外执行了let parameter = argument,在函数体内声明变量名为形参的局部变量,并且值为实参
this
函数内部this指向的对象取决于函数被调用的情形。
- 通过 new 操作符调用函数且函数没有明确的返回值时,this指向函数将要创建的对象
- 函数被当作对象的属性调用,this指向调用该函数的对象
- 通过call,apply,bind显示地给函数绑定调用对象
- 找不到对象的话就是宿主环境(window)
作用域
函数可以通过参数获得额外的变量,
函数也可以通过this对象来获得额外的变量,
函数还可以通过作用域获得额外的变量
相比于this对象,动态地获得额外的变量;通过作用域获得的额外的变量是在函数书写的时候就确定了,静态作用域
let x = 10;
function foo() {
console.log(x);
}
function bar(funArg) {
let x = 20;
funArg(); // 10
}
bar(foo);
函数在执行时,其上下文是基于它书写的地方
闭包
1 function foo() {
2 var a = 2;
3
4 function bar() {
5 console.log( a );
6 }
7
8 return bar;
9 }
10
11 var baz = foo();
12
13 baz(); // 2
- a 是 foo() 内部的变量,不能在函数外部被直接访问
- bar 可以访问 foo() 内部所有的变量,包括 a
- bar 被作为返回值,返回给了外部变量 baz,因此通过 baz 可以访问 foo() 内部的变量,包括 a
bar 内部包裹着一段代码 console.log(a)
,虽然它在第13行,通过 baz 来调用,但实际上它执行时的上下文仍是第5行的上下文
Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.
闭包的本质是作用域
本来,当 foo() 执行完后,这个作用域及其内部的变量就被回收了,但是
bar() still has a reference to that scope, and that reference is called closure.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。