简介
尽管 JavaScript 总是让人产生误解,但是它已经成为了最流行的编程语言之一。理解 JavaScript 的内在原理很困难。同样的,迫使 JavaScript 成为常规规范,如面向对象或函数编程,同样具有挑战性。这里我强调阐明 JavaScript 核心部分的原生函数。
在这篇文章中,我将讨论以下几种行为:
- Call/Apply
- Bind
- Map
- Filter
首先我会定义这个函数(利用Mozilla的声明方式),然后提供一个例子,最后实现此函数。
为了解释这些行为,我需要先解释一下复杂的 this
关键字以及类似数组的 arguments
对象。
this
和 arguments
对象
JavaScript 的作用域是基于函数而言的,术语一般称为作用域,变量和方法的作用域都是当前函数。此外,函数执行的作用域是他们被定义的作用域而不是执行的作用域。如果你想了解更多有关于作用域的知识,可以参考你应该知道的4种 JavaScript 设计模式这篇文章。this
对象引用当前函数的上下文并且可以以多种方式被调用。例如,它可以被绑定到 window
对象(全局作用域)。
1 2 3 4 5 6 7 |
this.globalVar = { myGlobalVarsMethod: function (){ // Implementation } }; console.log(this.globalVar); // { myGlobalVarsMethod: [Function] } |
并且变量可以绑定到已存在的函数中,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
this.globalVariable = 'globalVariable'; function globalFunction (){ this.innerVariable = 'innerVariable'; console.log(this.globalVariable === undefined); // false console.log(this.innerVariable === 'innerVariable'); // true return { innerFunction: function () { console.log(this.globalVariable === undefined); // true console.log(this.innerVariable === undefined); // true } } } globalFunction().innerFunction(); |
这里存在被绑定到每一个调用函数的 this
对象。严格模式下,如果变量未定义就会抛出异常/错误( TypeErrors )。在生产环境下严格模式者会被优先考虑;然而,我故意选择不使用此模式以避免抛出异常。下面是严格模式下的一个简单例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
this.globalVar = 'globalVar'; function nonStrictFunctionTest () { return function () { console.log(this.globalVar); // undefined } } function strictFunctionTest () { 'use strict'; // Strict Mode return function () { console.log(this.globalVar); // TypeError: Cannot read property 'globalVar' of undefined } } nonStrictFunctionTest()(); strictFunctionTest()(); |
可能很多 JavaScript 开发人员不知道,创建函数时会有一个arguments
对象。这是一个类似数组的对象(仅具有属性的长度)。arguments
主要有三个属性,即callee
(调用方法),length
,和caller
(调用函数的参考)。
在一个函数中声明变量参数会替换/覆盖原先的参数对象。
如下列出的一些参数对象:
1 2 3 4 5 6 7 8 9 10 |
function fn (){ console.log(typeof arguments); // [object Object] console.log(arguments[0]); // DeathStar console.log(arguments[1]); // Tatooine arguments.push("Naboo"); // TypeError: undefined is not a function var arguments = "Star Wars"; console.log(arguments[5]); // W } fn("DeathStar", "Tatooine"); |
按照如下所示,用 arguments
创建一个数组:
简介
尽管 JavaScript 总是让人产生误解,但是它已经成为了最流行的编程语言之一。理解 JavaScript 的内在原理很困难。同样的,迫使 JavaScript 成为常规规范,如面向对象或函数编程,同样具有挑战性。这里我强调阐明 JavaScript 核心部分的原生函数。
在这篇文章中,我将讨论以下几种行为:
- Call/Apply
- Bind
- Map
- Filter
首先我会定义这个函数(利用Mozilla的声明方式),然后提供一个例子,最后实现此函数。
为了解释这些行为,我需要先解释一下复杂的 this
关键字以及类似数组的 arguments
对象。
this
和 arguments
对象
JavaScript 的作用域是基于函数而言的,术语一般称为作用域,变量和方法的作用域都是当前函数。此外,函数执行的作用域是他们被定义的作用域而不是执行的作用域。如果你想了解更多有关于作用域的知识,可以参考你应该知道的4种 JavaScript 设计模式这篇文章。this
对象引用当前函数的上下文并且可以以多种方式被调用。例如,它可以被绑定到 window
对象(全局作用域)。
1 2 3 4 5 6 7 |
this.globalVar = { myGlobalVarsMethod: function (){ // Implementation } }; console.log(this.globalVar); // { myGlobalVarsMethod: [Function] } |
并且变量可以绑定到已存在的函数中,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
this.globalVariable = 'globalVariable'; function globalFunction (){ this.innerVariable = 'innerVariable'; console.log(this.globalVariable === undefined); // false console.log(this.innerVariable === 'innerVariable'); // true return { innerFunction: function () { console.log(this.globalVariable === undefined); // true console.log(this.innerVariable === undefined); // true } } } globalFunction().innerFunction(); |
这里存在被绑定到每一个调用函数的 this
对象。严格模式下,如果变量未定义就会抛出异常/错误( TypeErrors )。在生产环境下严格模式者会被优先考虑;然而,我故意选择不使用此模式以避免抛出异常。下面是严格模式下的一个简单例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
this.globalVar = 'globalVar'; function nonStrictFunctionTest () { return function () { console.log(this.globalVar); // undefined } } function strictFunctionTest () { 'use strict'; // Strict Mode return function () { console.log(this.globalVar); // TypeError: Cannot read property 'globalVar' of undefined } } nonStrictFunctionTest()(); strictFunctionTest()(); |
可能很多 JavaScript 开发人员不知道,创建函数时会有一个arguments
对象。这是一个类似数组的对象(仅具有属性的长度)。arguments
主要有三个属性,即callee
(调用方法),length
,和caller
(调用函数的参考)。
在一个函数中声明变量参数会替换/覆盖原先的参数对象。
如下列出的一些参数对象:
1 2 3 4 5 6 7 8 9 10 |
function fn (){ console.log(typeof arguments); // [object Object] console.log(arguments[0]); // DeathStar console.log(arguments[1]); // Tatooine arguments.push("Naboo"); // TypeError: undefined is not a function var arguments = "Star Wars"; console.log(arguments[5]); // W } fn("DeathStar", "Tatooine"); |
按照如下所示,用 arguments
创建一个数组: