1

数据类型

在最新的 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

Untitled Diagram (http://ipic-nbb3210.oss-cn-beijing.aliyuncs.com/td1ci.jpg).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
  1. a 是 foo() 内部的变量,不能在函数外部被直接访问
  2. bar 可以访问 foo() 内部所有的变量,包括 a
  3. 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.

nbb3210
436 声望31 粉丝

优雅地使用JavaScript解决问题


« 上一篇
重构smart-import
下一篇 »
解构小结