JobbyM's Blog

first do it, then do it right, then do it better.


  • 首页

  • 分类

  • 归档

  • 标签

  • 搜索
JobbyM's Blog

一日一练-JS 了解this

发表于 2018-04-28 | 分类于 技术 | | 阅读次数

子曰:this 是什么?

什么是this

this 不是编写时绑定,而是运行时绑定。它依赖于函数调用的上下文条件。this 绑定与函数声明的位置没有任何关系,而于函数被调用的方式紧密相连。

当一个函数被调用时,会建立一个称为执行环境的活动记录。这个记录包含函数是从何处(调用–call-stak)被调用的,韩式是如何被调用的,被传递了什么参数等信息。这个记录的属性之一,就是函数执行期间将被使用的this 引用。

this 实际上是在函数被调用时建立的一个绑定,它指向什么是完全由函数被调用的调用点(call-site)来决定的。

阅读全文 »
JobbyM's Blog

一日一练-JS 了解typeof 和instanceOf

发表于 2018-04-28 | | 阅读次数

JavaScript 拥有带类型的值,没有带类型的变量。变量可以在任何时候,持有任何值。
基本(primitive)类型

  1. null
  2. undefined
  3. boolean
  4. number
  5. string
  6. object
  7. symbol – 在ES6 中被加入的

使用typeof 可以判断一个值的类型是什么,而且总是返回七种字符串值(注意,类型是字符串)中的一种。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var a = null
typeof a // 'object'

var a
typeof a // 'undefined'

var a = true
typeof a // 'boolean'

var a = 1
typeof a // 'number'

var a ='hello world'
typeof a // 'string'

var a = {b: 'c'}
typeof a // 'object'

var a = Symbol()
typeof a // 'symbol'

var a = []
typeof a // 'object'

var a = function () {}
typeof a // 'function'

注意:
1.如果你想要使用null 类型来测试null 值,你需要一个复合条件:

1
2
var a = null
(!a && typeof a === 'object') // true

2.可以看到typeof 可以返回function。

1
typeof function a () { /* ... */} === 'function' // true

但是function 不是JS 中的一种顶层的内建类型。它实际上是对象(object) 的“子类型”。特别地,一个函数(function)被称为“可调用对象” – 一个拥有[[Call]] 内部属性,运行被调用的对象。
3.对于数组

1
typeof [] === 'object' // true

它也仅仅是对象。将它们认为是对象的“子类型”,带有被数字索引的附加性质(与仅仅使用字符串键的普通对象相反),并维护着一个自动更新的.length 属性。
4.注意“undefined” 与“undeclared” 的区别

1
2
3
var a
a // undefined
b // ReferenceError: b is not defined

一个“undefined” 变量是在可访问的作用域中已经被声明过的,但是在 这个时刻 它里面没有任何值。相比之下,一个“undeclared” 变量是在可访问的作用域中还没有被正式声明的。
“undefined” 同“is not defined” 是非常不同的。
5.当typeof 一个未被声明的变量的返回值

1
2
3
4
var a

typeof a // "undefined"
typeof b // "undefined"

typeof 操作符甚至为“undeclared”(或“not defined”)变量返回'undefined'。当我们执行typeof b 时,即使b 是一个未声明变量,也不会有错误被抛出。这是typeof 的一种特殊的安全防卫行为。

参考文档

  1. 你不了解的JS 入门与进阶
  2. 深入理解javascript之typeof和instanceof CSDN
JobbyM's Blog

一日一练-JS 了解Thunk 函数

发表于 2018-04-28 | 分类于 技术 | | 阅读次数

子曰:到底什么是thunk?

thunk、thunkify、甚至React 还有一个叫redux-thunk,为什么都有一个thunk 呢?在通读《You Dont Know JS》 时,看到了作者Kyle Simposn对thunk 的解释,对thunk 有了一定的了解,同时参考了阮一峰的 Thunk 函数的含义和用法,通过对比将其摘录下来。

Thunk 的历史

20 世纪60 年代在编程语言刚起步时,计算机科学家研究编译器怎么写比较好(注意,是编译器而不是JavaScript)。一个争议点是“求值策略”,即函数的参数到底应该合适求值。

1
2
3
4
5
6
7
var x = 1

function foo (m) {
return m * 2
}

f(x + 5)

x + 5 表达式合适求值?

1. 传值调用(call by value)
在进入函数体之前,就计算x + 5 的值(等于6),再将这个值传入函数foo。C 语言就采用这种策略。

1
2
3
foo(x + 5)
// 传值调用时,等同于
foo(6)

2. 传名调用(call by name)
直接将表达式x + 5 传入函数体,只在用到它的时候求值。Haskell 语言采用这种策略。

1
2
3
foo(x + 5)
// 传名调用时,等同于
(x + 5) * 2
阅读全文 »
JobbyM's Blog

一日一练-JS 了解尾调用优化

发表于 2018-04-28 | 分类于 技术 | | 阅读次数

子曰:尾调用-> 尾调用优化
下面大部分内容来自ESMAScript 6 入门 尾调用优化 阮一峰

什么是尾调用

尾调用(Tail Call)是函数式编程的一个重要概念,就是指某个函数的最后一步是调用另一个函数。

1
2
3
function foo (x) {
return bar (x)
}

上面代码中,函数foo 的最后一步是调用函数bar,这就叫尾调用。

阅读全文 »
JobbyM's Blog

一日一练-JS 了解ES6 模块

发表于 2018-04-25 | 分类于 技术 | | 阅读次数

子曰:最终的杀器-ES6 模块

概述

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

ES6 模块不是对象,而是通过export 命令显式指定输出的代码,再通过import 命令输入。

1
2
// ES6 模块
import { stat, exists, readFile } from 'fs'

上面代码的实质是从fs 模块加载3 个方法,其他方法不加载。这种加载称为“编译时加载” 或者静态加载,即ES6 可用于在编译时就完成模块加载,效率要比CommonJS 模块的加载方式高。

由于ES6 模块是编译时加载,使得静态分析成为可能。

需要注意this 的限制。ES6 模块之后,顶层的this 指向undefined,即不应该在顶层代码使用this。

阅读全文 »
JobbyM's Blog

一日一练-JS 了解UMD 规范

发表于 2018-04-25 | 分类于 技术 | | 阅读次数

子曰:{AMD + CommonJS} = UMD
翻译自UMD github

UMD(Universal Module Definition,通用模块定义)

该库正式化了用于JavaScript 模块的UMD API的设计和实现。这些模块能够在任何地方工作,无论是在客户端,服务器还是其他地方。

UMD 模式通常会尝试提供适配当前最流行的脚本加载器(例如RequireJS等)的兼容性。在许多情况下,它使用AMD作为基础,并添加了特殊方式来处理CommonJS兼容性。

UMD的实现很简单,先判断是否支持NodeJS模块格式(exports是否存在),存在则使用NodeJS模块格式。
再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。前两个都不存在,则将模块公开的全局(window或global)。

阅读全文 »
JobbyM's Blog

一日一练-JS 了解CMD 规范

发表于 2018-04-25 | 分类于 技术 | | 阅读次数

子曰:了解了AMD,之后了解CMD 规范
翻译自通用模块定义 草案

CMD 定义

CMD(Common Module Definition,通用模块定义)本规范说明了如何编写模块以便在 基于浏览器 的环境中实现互操作。通过暗示,本规范定义了模块系统为支持可互操作模块而必须提供的最小功能。

  • 模块是单例模式。
  • 在模块范围内的不应引入新自由变量。
  • 执行必须是懒惰的。

模块定义

一个模块是用define 关键字定义的,这是一个函数。

1
define(factory)
  1. define 函数接受一个参数,即模块factory。
  2. factory 可能是一个函数或其他有效的值。
  3. 如果factory 是一个函数,则该函数的前三个参数(如果指定)必须依次为require,exports和module。
  4. 如果factory 不是一个函数,那么模块的导出就被设置为该对象。

模块上下文

在一个模块中,有三个自由变量:require,exports和module。

1
2
3
define( function (require, exports, module) {
//模块代码在这里
})

require 函数

  1. require 是一个函数
    1.1. require 接受一个模块标识符。
    1.2. require 返回外部模块的输出API。
    1.3. 如果请求的模块不能被返回,那么require应该返回null。
  2. require.async 是一个函数
    2.1. require.async 接受模块标识符列表和一个可选的回调函数。
    2.2. 回调函数接收模块导出作为函数参数,按照与第一个参数中的顺序相同的顺序列出。
    2.3. 如果被请求的模块不能被返回,则回调应该相应地收到null。

exports 对象

在一个模块中,有一个名为exports 的自由变量,这是模块在执行时可以添加其API的对象。

module 对象

  1. module.uri
    模块uri 的解析。
  2. module.dependencies
    模块所需的模块标识符列表。
  3. module.exports
    模块的导出API。它与exports 对象相同。

模块标识符

  1. 模块标识符是且必须是 字面量 字符串。
  2. 模块标识符可能没有像.js这样的文件扩展名。
  3. 模块标识符应该是像foo-bar 使用- 进行连接。
  4. 模块标识符可以是相对路径,如./foo 和../bar。

示例代码

一个典型的例子
math.js

1
2
3
4
5
6
7
8
9
define(function (require, exports, module) {
exports.add = function () {
var sum = 0, i = 0, args = argments, l = args.length
while (i < l) {
sum += args[i ++]
}
return sum
}
})

increment.js

1
2
3
4
5
6
define( function (require, exports, module) {
var add = require('math').add
exports.increment = function (val) {
return add(val, 1)
}
})

program.js

1
2
3
4
5
6
7
define(function (require, exports, module) {
var inc = require('increment').increment
var a = 1
inc(a) // 2

module.id = 'program'
})

用非函数factory包装模块
object-data.js

1
2
3
define({
foo: 'bar'
})

array-data.js

1
2
3
4
define([
'foo',
'bar'
])

string-data.js

1
define('foo bar')

相关文档

  1. CMD 模块定义规范
  2. RequireJS 和Sea.js 异同
JobbyM's Blog

一日一练-JS 了解AMD 规范

发表于 2018-04-24 | 分类于 技术 | | 阅读次数

本文主要翻译自github amdjs
子曰:了解了CommonJS 规范,再了解一下AMD 规范

AMD 定义

AMD(Asynchronous Module Definition,异步模块定义)指定了一种定义模块的机制,以便可以异步加载模块及其依赖关系。 这尤其适用于模块的同步加载会导致性能,可用性,调试和跨域访问问题的浏览器环境。

模块定义

该规范定义了一个可用作自由变量或全局变量的单个函数define() 函数

1
define(id?, dependencies?, factory)

关于参数:

  1. id
    1.1. 是一个字符串字面量。 它指定了正在定义的模块的ID。 这个参数是可选。

  2. dependencies
    2.1 是数组字面量,它是正在定义的模块所需的依赖关系。必须在执行模块工厂函数之前解析依赖关系,并将解析值作为参数传递给工厂函数,dependencies元素的顺序和factory参数一一对应

    2.2. 本规范定义了三个具有不同的特殊依赖项名称。如果中出现require,exports或module的值,则该参数应解析为由CommonJS模块规范定义的相应变量。

    2.3. 依赖关系参数是可选的。如果省略,它应该默认为 ["require", "exports", "module"]。但是,如果factory 函数的arity(长度属性)小于3,那么加载器可能会选择仅使用与该函数的arity或长度相对应的参数数目来调用factory。

  3. factory
    3.1. 是一个应该被执行来实例化模块或对象的函数。 如果factory是一个函数,它应该只执行一次。 如果factory参数是一个对象,则该对象应该被指定为模块的导出值。

    3.2. 如果factory函数返回一个值(一个对象,函数或强制为true的任何值),则应该将该值指定为模块的导出值。

阅读全文 »
JobbyM's Blog

一日一练-JS 了解CommonJS 规范

发表于 2018-04-24 | 分类于 技术 | | 阅读次数

子曰:CMD、AMD傻傻分不清,那就先了解一下CommonJS规范
摘自《深入浅出Node.js》(田永强@朴灵 )

CommonJS 规范

CommonJS 规范为JavaScript 制定了一个美好的愿景–希望JavaScript 能够在任何地方运行

CommonJS 的出发点

主要是为了拟补当前JavaScript 没有标准的缺陷,以达到像Python 具备开发大型应用的能力,而不是停留在小脚本程序的阶段。期望用CommonJS API 写出的应用可以具备跨宿主环境执行的能力,这样不仅可以利用JavaScript 开发客户端应用,还可以编写以下应用

  1. 服务器端JavaScript 应用程序
  2. 命令行工具
  3. 桌面图形界面应用程序
  4. 混合应用
阅读全文 »
JobbyM's Blog

一日一练-JS toString 和valueOf 方法的联系与区别

发表于 2018-04-23 | 分类于 技术 | | 阅读次数

子曰:类型转换中toString 和valueOf 的联系与区别分析

首先是看看ES5 的规范是如何进行说明的

在这里有几个基础知识点需要了解一下:

  1. [[Class]]
    [[Class]] 属于Object 的内部属性,值的类型返回为String,其作用是,说明规范定义的对象分类的一个字符串值。
    ES5 规范的每种内置对象都定义了[[Class]] 内部属性值。宿主对象的[[Class]] 内部属性值可以是除了“Arguments”、 “Array”、 “Boolean”、 “Date”、 “Error”、 “Function”、 “JSON”、 “Math”、 “Number”、 “Object”、 “RegExp”、 “String” 的任意字符串。[[Class]] 内部属性的值用于内部区分对象的种类。注,本规范中除了通过Object.prototype.toString 没有提供任何手段使程序访问此值。

    摘自ES5 类型

阅读全文 »
<i class="fa fa-angle-left"></i>1…111213…22<i class="fa fa-angle-right"></i>
JobbyM

JobbyM

first do it, then do it right, then do it better.

213 日志
1 分类
110 标签
GitHub Weibo
  • 阮一峰的网络日志
  • w3cplus
  • 张鑫旭的个人博客
© 2016 - 2021 JobbyM
由 Hexo 强力驱动
主题 - NexT.Pisces