博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习JavaScript原生函数以及如何使用它们
阅读量:2514 次
发布时间:2019-05-11

本文共 13533 字,大约阅读时间需要 45 分钟。

( )

JavaScript is becoming the most popular programming language though it is very misunderstood. Understanding JavaScript's internals is tough. Similarly, coercing JavaScript into a more conventional paradigm, such as Object Oriented or Functional Programming can be equally challenging. I want to highlight key native functions with hopes to elucidate JavaScript's innards.

尽管JavaScript被误解,但它正成为最受欢迎的编程语言。 了解JavaScript的内部原理很困难。 同样,将JavaScript强制转换为更传统的范例(例如面向对象或函数式编程)也同样具有挑战性。 我希望突出显示本机的关键功能,以期阐明JavaScript的内在特性。

In this article, I discuss the following behaviors:

在本文中,我讨论以下行为:

  • Call/Apply

    致电/申请
  • Bind

    绑定
  • Map

    地图
  • Filter

    过滤

I first define the function (with Mozilla's signature), then provide an example, and lastly implement it.

首先定义函数(带有Mozilla签名),然后提供示例,最后实现它。

To explain these behaviors, I need to expound on the convoluted 'this' keyword as well as the 'arguments' array-like object.

为了解释这些行为,我需要阐述复杂的“ this”关键字以及“ arguments”类数组对象。

( )

JavaScript's scoping is function-based, formally known as , variables and methods' scopes are within the current function. To read more on scopes, check out . The 'this' object references the present function context and used in several ways. For instance, it can be bound to the window (globally scoped).

JavaScript的范围是基于函数的,正式称为 ,变量和方法的范围在当前函数之内。 要阅读有关范围的更多信息,请查看 。 “ this”对象引用当前函数上下文并以多种方式使用。 例如,它可以绑定到窗口(全局作用域)。

this.globalVar = {
myGlobalVarsMethod: function (){
// Implementation }};console.log(this.globalVar); // { myGlobalVarsMethod: [Function] }

And variables can be bound to the containing function, like so:

变量可以绑定到包含函数,如下所示:

this.globalVariable = 'globalVariable';function globalFunction (){
this.innerVariable = 'innerVariable'; console.log(this.globalVariable === undefined); // true console.log(this.innerVariable === 'innerVariable'); // true return {
innerFunction: function () {
console.log(this.globalVariable === undefined); // true console.log(this.innerVariable === undefined); // true } }}globalFunction().innerFunction();

There are separate 'this' objects bound to each invoking function. seeks to secure applications by throwing exceptions/erros () if variables are undefined. In production environments strict mode is preferred; however, I purposefully opt out for the rest of this article to avoid thrown errors. Here is a simple example of strict mode:

每个调用函数都有单独的“ this”对象。 如果变量未定义, 试图通过抛出异常/错误( )来保护应用程序的安全。 在生产环境中,首选严格模式。 但是,我有意选择退出本文的其余部分,以避免引发错误。 这是严格模式的简单示例:

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()();

Unbeknownst to many Javascript developers, there is an arguments object created within a function. It is an Array-like object (only having the property length). Arguments has three main properties, namely, callee (the invoking method), length, and caller (the reference to invoked function).

许多Javascript开发人员都不知道,在函数内创建了一个arguments对象。 它是一个类似数组的对象(仅具有属性长度)。 参数具有三个主要属性,即被调用方 (调用方法), 长度调用方 (对被调用函数的引用)。

Declaring a variable arguments inside a function replaces/overrides the primary arguments object.

在函数内部声明变量参数将替换/覆盖主要参数对象。

The following showcases the arguments object:

以下展示了arguments对象:

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");

To create an array with the arguments, take this route:

要创建带有参数的数组,请遵循以下路线:

var args = Array.prototype.slice.call(arguments);

( )

Both call and apply are used to invoke a method on an object. In contrasting to using the dot operator, call and apply both accept this as the first argument. As described above, every function maintains a specific scope in which it is defined. Therefore, you must take into account the function's scope when invoked on the object.

调用应用均用于调用对象上的方法。 与使用点运算符相比, 调用应用都接受作为第一个参数。 如上所述,每个功能都维护其定义的特定范围。 因此,在对象上调用函数时,必须考虑到函数的作用域。

Mozilla's and signatures are, respectively, as follows:

Mozilla的和签名分别如下:

fun.apply(thisArg, [argsArray])fun.call(thisArg[, arg1[, arg2[, ...]]])

By explicitly passing thisArg, the invoking function can access or modify objects in the particular context. The following example clarifies call's use.

通过显式传递thisArg ,调用函数可以访问或修改特定上下文中的对象。 以下示例阐明了call的用法。

this.lightSaberColor = 'none';var darthVader = {
team: 'Empire', lightSaberColor: 'Red'};var printLightSaberColor = function(){
console.log(this.lightSaberColor);}printLightSaberColor() // noneprintLightSaberColor.call(darthVader); // RedprintLightSaberColor.apply(darthVader); // Red

Notice that the first invocation defaults to the global scope (window), however, the second one resolves to darthVader.

请注意,第一个调用默认为全局范围(窗口),但是,第二个调用解析为darthVader。

The main difference between using call and apply is their signature. Call requires an explicit list of arguments separately passed in, whereas apply requires an array consisting of the arguments. I remember it by this mnemonic: "Apply uses an Array." Apply is more suitable when your program is not aware of the number of arguments.

使用callapply之间的主要区别在于它们的签名。 调用需要一个单独传入的参数的显式列表,而apply需要一个由参数组成的数组。 我这个记忆还记得:“ 一个 pply使用一个A rray” 当程序不知道参数数量时, Apply更适合。

(partial function application) is a functional programming use case for call and apply. Currying allows us to create functions that return functions requiring a subset of arguments with predetermined conditions. Here is a currying function:

(部分功能应用程序)是用于callapply的功能编程用例。 使用Currying,我们可以创建函数,以返回需要具有预定条件的参数子集的函数。 这是一个currying函数:

var curry = function(fun) {
// nothing to curry. return function if (arguments.length < 1) {
return this; } // Create an array with the functions arguments var args = Array.prototype.slice.call(arguments, 1); return function() {
// *Apply* fn with fn's arguments return fun.apply(this, args.concat(Array.prototype.slice.call(arguments, 0))); };};// Creating function that already predefines adding 1 to afunction addOneToNumber(a) {
console.log(1 + a);}// addOneCurried is of functionvar addOneCurried = curry(addOneToNumber);console.log(addOneCurried(10)); // 11

Even though arguments is not an array, Array.prototype.slice can transform Array-like objects to new arrays.

即使参数不是数组, Array.prototype.slice仍可以将类似Array的对象转换为新数组。

( )

The bind method is used to invoke methods while explicitly specifying this. Similar to call and apply, scoping matters. It is useful for when you need to bind an object to a function's this object.

bind方法用于在显式指定this的同时调用方法。 类似于呼叫应用 ,范围界定问题 。 当您需要对象绑定到函数的对象时,它很有用。

Below is bind's :

下面是bind的 :

fun.bind(thisArg[, arg1[, arg2[, ...]]])

In layman's terms, we are taking function fun and passing thisArg through it. Essentially, whenever this is called in fun, it is referring to thisArg. Let's take a closer look at a simple example:

用外行的话来说,我们正在使函数有趣并通过它传递thisArg 。 从本质上讲,只要就是所谓的乐趣 ,它指的是thisArg。 让我们仔细看一个简单的例子:

var lukeSkywalker = {
mother: 'Padme Amidala', father: 'Anakin Skywalker'.}var getFather = function(){
console.log(this.father);}getFather(); // undefinedgetFather.bind(lukeSkywalker)(); // Anakin SkywalkergetFather(lukeSkywalker); // undefined

The first getFather() returns undefined because the father attribute is not set on this. Then what is this? It is the global window object since we did not explicitly set it! The second getFather() returns "Anakin Skywalker" because lukeSkywalker is getFather()'s this. Many Java/C++ developers would assume the last getFather() call would return the desired result - though once again, this is bound to global.

第一getFather()返回undefined因为父亲属性未在设置。 那么是什么? 因为我们没有显式设置它,所以它是全局窗口对象! 第二个getFather()返回“ Anakin Skywalker”,因为lukeSkywalker是getFather()this 。 许多Java / C ++开发人员会假设最后一次getFather()调用将返回所需的结果-尽管再次其绑定到global

Here is the implementation of bind:

这是bind的实现:

Function.prototype.bind = function(scope) {
var _that = this; return function() {
return _that.apply(scope, arguments); }}

Consequent to Javascript's lexical scoping, the returned function's this object is different to bind's. Hence, _that is set to *this* to maintain the correct scope. Otherwise, this.apply(scope, arguments)would be undefined.

根据Javascript的词法作用域,返回函数的this对象不同于bind的。 因此,将_that设置为* this *以保持正确的范围。 否则, this.apply(scope, arguments)将是不确定的。

( )

Javascript's map function is a functional programming technique for iterating over an array while transforming each element. It creates a new array with the 'modified' elements returned in a callback. I mention modifying or transforming elements, though if the elements are objects (not primitives), good practice dictates cloning the object rather than physically altering the original one.

Javascript的map函数是一种功能编程技术,用于在变换每个元素的同时迭代数组。 它使用在回调中返回的'modified'元素创建一个新数组。 我提到了修改或转换元素,尽管如果元素是对象(而不是基元),那么良好的做法要求克隆对象而不是物理地更改原始对象。

Here is the method signature:

这是方法签名:

arr.map(callback[, thisArg])

The callback method has three parameters, namely, currentValue, index, and array.

回调方法具有三个参数,即currentValueindexarray

Here is a simple example of map:

这是map的一个简单示例:

function Jedi(name) {
this.name = name;}var kit = new Jedi('Kit');var count = new Jedi('Count');var mace = new Jedi('Mace');var jedis = [kit, count, mace];var lastNames = ['Fisto', 'Dooku', 'Windu'];var jedisWithFullNames = jedis.map(function(currentValue, index, array) {
var clonedJedi = (JSON.parse(JSON.stringify(currentValue))) // Clone currentValue clonedJedi.name = currentValue.name + " " + lastNames[index]; return clonedJedi;});jedisWithFullNames.map(function(currentValue) {
console.log(currentValue.name);});/**Output:Kit FistoCount DookuMace Windu*/

With an understanding of what map does, take a look at its implementation:

了解地图的功能后,看看它的实现:

Array.prototype.map = function (fun, thisArg) {
if(typeof fun !== 'function') {
throw new Error("The first argument must be of type function"); } var arr = []; thisArg = (thisArg) ? thisArg : this; thisArg.forEach(function(element) {
arr[arr.length] = fun.call(thisArgs, element); }); return arr;}

*[Note: this is a simple implementation. To see ECMAscript 5's full implementation, check out its .]*

* [注意:这是一个简单的实现。 要查看ECMAscript 5的完整实施,请查看其 。] *

( )

The filter method is another array behavior. Similar to map, filter returns a new array and accepts a function and an optional thisArg. However, the returned array contains only elements that fit a certain condition tested in the callback function. The callback function must return a boolean - returning true signals the element to be accepted and inserted into the returned array.

filter方法是另一种数组行为。 与map相似, filter返回一个新数组,并接受一个函数和一个可选的thisArg 。 但是,返回的数组仅包含符合在回调函数中测试的特定条件的元素。 回调函数必须返回一个布尔值-返回true表示该元素将被接受并插入返回的数组中。

There are many use cases for filter, including picking the even integers, selecting objects with a particular property, or choosing valid phone numbers.

过滤器有很多用例,包括选择偶数整数,选择具有特定属性的对象或选择有效的电话号码。

Here is the method signature:

这是方法签名:

arr.filter(callback[, thisArg])

Once again, thisArg is optional and the callback function accepts three paramters, currentValue, index, and array.

再一次, thisArg是可选的,并且回调函数接受三个参数, currentValueindexarray

Here is an example of filter:

这是过滤器的示例:

function Person(name, side) {
this.name = name; this.side = side;}var hanSolo = new Person('Han Solo','Rebels');var bobaFett = new Person('Boba Fett','Empire');var princessLeia = new Person('Princess Leia', 'Rebels');var people = [hanSolo, bobaFett, princessLeia];var enemies = people.filter(function (currentValue, index, array) {
return currentValue.side === 'Empire';}).map(function(currentValue) {
console.log(currentValue.name + " fights for the " + currentValue.side + ".");});/**Output:Boba Fett fights for the Empire.*/

Interestingly, array methods are chainable to create fun and complex operations.

有趣的是,数组方法可链接以创建有趣且复杂的操作。

Lastly, lets take a look at filter's implementation:

最后,让我们看一下filter的实现:

Array.prototype.filter = function(fun, thisArg) {
if(typeof fun !== 'function') {
throw new Error("The first argument must be of type function"); } var arr = []; thisArg = (thisArg) ? thisArg : this; thisArg.forEach(function(element) {
if (fun.call(thisArg, element)) {
arr[arr.length] = element; } }); return arr;};

*[Here is the spec for ECMAscript's ]*

* [这是ECMAscript的规范] *

( )

There are many more native functions that prove useful though these happen to be the most confusing. It is worth reviewing every method on and .

尽管碰巧最令人困惑,但还有许多本机函数被证明是有用的。 值得回顾一下关于和每种方法。

Hopefully, this gives an insight into Javascript's internals and clarifies Javascript's confusing lexical scope. Call, apply, and bind are tricky to grasp though it becomes more fluid with practice. Try to implement map and filter whenever possible while avoiding traditional looping techniques.

希望这可以深入了解Javascript的内部结构,并阐明Javascript令人困惑的词汇范围。 调用,应用和绑定很难掌握,尽管在实践中变得更加流畅。 尽可能避免使用传统的循环技术,尝试实现映射和过滤器。

翻译自:

转载地址:http://znywd.baihongyu.com/

你可能感兴趣的文章
《Apache服务之php/perl/cgi语言的支持》RHEL6——服务的优先级
查看>>
Linux 部署 Django 系统
查看>>
java 异常处理2
查看>>
Bugku Crack it
查看>>
[React] Recompose: Theme React Components Live with Context
查看>>
[React] Creating a Stateless Functional Component
查看>>
python字符串截取子串
查看>>
【Android】Linux编译环境OpenJDK的版本修改到1.8
查看>>
【Spring】17、spring cache 与redis缓存整合
查看>>
【Linux命令】ps命令
查看>>
CentOS6.x的163yum配置
查看>>
C#中ref和out的使用小结
查看>>
Powershell-远程操作
查看>>
Java基础学习笔记二十一 多线程
查看>>
使用Java Low Level REST Client操作elasticsearch
查看>>
css3 抖动
查看>>
移动端手势
查看>>
[Linked List]Insertion Sort List
查看>>
Product of Array Except Self
查看>>
[Tree]Binary Tree Inorder Traversal
查看>>