手把手教你创建第一个React Native自动化测试工具Detox

本文主要是介绍手把手教你创建第一个React Native自动化测试工具Detox,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

a+b:动态类型是灾难之源还是最好的特性?(上)

动态类型是 JavaScript 的动态语言特性中最有代表性的一种。动态执行与动态类型是天生根植于 JavaScript 语言核心设计中的基础组件,它们相辅相成,导致了 JavaScript 在学习上是易学难精,在使用中是易用易错。是好是坏难以定论。

类型系统的简化

从根底上来说,JavaScript 有着两套类型系统,如果仅以此论,那么还算不上复杂。 但是 ECMAScript 对语言类型的约定,又与 JavaScript 原生的、最初的语言设计不同,这导致了各种解释纷至沓来,很难统一成一个说法。而且,ECMAScript 又为规范书写而订立了一套类型系统,并不停地演进它。这就如同雪上加霜,导致 JavaScript 的类型系统越发地说不清楚了。 在讨论动态类型的时候,可以将 JavaScript 类型系统做一些简化,从根底里来说, JavaScript 也就是 typeof() 所支持的 7 种类型,其中的“对象(object)”与“函数 (function)”算一大类,合称为引用类型,而其他类型作为值类型。 无论如何,我们且先以这种简单的类型划分为基础,来讨论 JavaScript 中的动态类型。因为这样一来,JavaScript 中的类型转换变得很简单、很干净,也很易懂,可以用两条规则概括如下:

1.从值 x 到引用,调用 Object(x) 函数。
2.从引用 x 到值,调用 x.valueOf() 方法;或调用 4 种值类型的包装类函数,例如 Number(x),或者 String(x) 等等。

简单吧?当然不会这么简单。

先搞定一半

在类型转换这件事中,有“半件”是比较容易搞定的。 这个一半,就是“从值 x 到引用”。因为主要的值类型都有对应的引用类型,因此 JavaScript 可以用简单方法一一对应地将它们转换过去。 使用Object(x)来转换是很安全的方法,在用户代码中不需要特别关心其中的x是什么样的数据——它们可以是特殊值(例如 null、undefined 等),或是一般的值类型数据,又或者也可以是一个对象。所有使用 Object(x) 的转换结果,都将是一个尽可能接近你的预期的对象。例如,将数字值转换成数字对象:

x = 1234;
Object(x); 
[Number: 1234] 

类似的还包括字符串、布尔值、符号等。而 null、undefined 将被转换为一个一般的、空白的对象,与new Object或一个空白字面量对象(也就是{ })的效果一样。这个运算非常好用的地方在于,如果 x 已经是一个对象,那么它只会返回原对象,而不会做任何操作。也就是说,它没有任何的副作用,对任何数据的预期效果也都是“返回一个对象”。而且在语法上,Object(x)也类似于一个类型转换运算,表达的是将任意x转换成对象x。 简单的这“半件事”说完后,我们反过来,接着讨论将对象转换成值的情况。

值 VS 原始值(Primitive values)

任何对象都会有继承自原型的两个方法,称为 toString() 和 valueOf(),这是 JavaScript 中“对象转换为值”的关键。 一般而言,你可以认为“任何东西都是可以转换为字符串的”,这个很容易理解,比如 JSON.stringify() 就利用了这一个简单的假设,它“几乎”可以将 JavaScript 中的任何对象或数据,转换成 JSON 格式的文本。

所以在 JavaScript 中将任何东西都转换成字符串这一点,在具体的处理技术上并不存在什么障碍。 但是如何理解“将函数转换成字符串”呢? 从最基础的来说,函数有两个层面的含义,一个是它的可执行代码,也就是文本形式的源代码;另一个则是函数作为对象,也有自己的属性。 所以,函数也可以被作为一个对象来转换成字符串,或者说,序列化成文本形式。 又或者再举一个例子,我们需要如何来理解将一个“符号对象”转换成“符号”呢?是的, 我想你一定会说,没有“符号对象”这个东西,因为符号是值,不是对象。其实这样讲只是对了一半,因为现实中确实可以将一个“符号值”转换为一个“符号对象”,例如:

(new Object).toString() 
'[object Object]' 

为了将这个问题“一致化”——也就是将问题收纳成更小的问题,JavaScript 约定,所有“对象 -> 值”的转换结果要尽量地趋近于 string、number 和 boolean 三者之一。不过这从来都不是书面的约定,而是因为 JavaScript 在早期的作用,就是用于浏览器上的开发,而:

  • 浏览器可以显示的东西,是 string;
  • 可以计算的东西,是 number;
  • 可以表达逻辑的东西,是 boolean。

因此,在一个“最小的、可以被普通人理解的、可计算的程序系统中”,支持的“值类型数 据”的最小集合,就应该是这三种。

这个问题不仅仅是浏览器,就算是一台放在云端的主机,你想要去操作它,那么通过控制台登录之后的 shell 脚本,也必须支持它。更远一点地说,你远程操作一台计算机,与浏览器用户要使用 gmail,这二者在计算的抽象上是一样的,只是程序实现的复杂性不一样而已。

所以,对于 ECMAScript 5 JavaScript 来说,当它支持值转换向对应的对象时,或者反过来从这些对象转换回值的时候,所需要处理的也无非是这三种类型而已。而处理的具体方法也很简单,就是在使用Object(x)来转换得到的对象实例中添加一个内部槽,存放这个x的值。更确切地说,下面两行代码在语义上的效果是一致的:

obj = Object(x); 
// 等效于(如果能操作内部槽的话) 
obj.[[PrimitiveValue]] = x; 

于是,当需要从对象中转换回来到值类型时,也就是把这个PrimitiveValue值取出来就 可以了。而“取出这个值,并返回给用户代码”的方法,就称为valueOf()。 到了 ECMAScript 6 中,这个过程就稍稍有些不同,这个内部槽是区别值类型的,因此为每种值类型设计了一个独立的私有槽名字。加上 ES8 中出现的大整数类型(BigInt),一共就有了 5 个对应的私有槽:[[BooleanData] [[NumberData]]、[[StringData] [[SymbolData]]和[[BigIntData]]。

那么在 ECMAScript 6 之后,除[[PrimitiveValue]]这个私有槽变成了 5 种值类型对应的、独立的私有槽之外,还有什么不同呢?

是的,这个你可能也已经注意到了。ECMAScript 6 之后还出现了Symbol.toPrimitive 这个符号。而它,正是将原本的[[PrimitiveValue]]这个私有槽以及其访问过程标准化,然后暴露给 JavaScript 用户编程的一个界面。

说到这里,就必须明确一般的值(Values)与原始值(Primitive values)之间的关系了。不过,在下一步的讨论之前,先总结一下前面的内容:也就是说,从typeof(x)的 7 种结果类型来看,其中 string、boolean、number、 bigint 和 symbol 的值类型与对象类型转换,就是将该值存入私有槽,或者从私有槽中把相应的值取出来就好了。 在语言中,这些对应的对象类型被称为“包装类”,与此相关的还有“装箱”与“拆箱”等行为,这也是后续会涉及到的内容。

所以,一种关于“原始值”的简单解释是:所有 5 种能放入私有槽(亦即是说它们有相应的包装类)的值(Values),都是原始值;并且,再加上两个特殊值 undefined 和 null, 那么就是所谓原始值(Primitive values)的完整集合了。 接下来,如果转换过程发生在“值与值”之间呢?

隐式转换

由于函数的参数没有类型声明,所以用户代码可以传入任何类型的值。对于 JavaScript 核心库中的一些方法或操作来说,这表明它们需要一种统一、一致的方法来处理这种类型差异。例如说,要么拒绝“类型不太正确的参数”,抛出异常;要么用一种方式来使这些参 数“变得正确”。 后一种方法就是“隐式转换”。但是就这两种方法的选择来说,JavaScript 并没有编码风格层面上的约定。基本上,早期 JavaScript 以既有实现为核心的时候,倾向于让引擎吞掉类型异常(TypeError),尽量采用隐式转换来让程序在无异常的情况下运行;而后期,以 ECMAScript 规范为主导的时候,则倾向于抛出这些异常,让用户代码有机会处理类型问题。

隐式转换最主要的问题就是会带来大量的“潜规则”。 例如经典的String.prototype.search®方法,其中的参数从最初设计时就支持在r参数中传入一个字符串,并且将隐式地调用r = new RegExp®来产生最终被用来搜索的正则表达式。而new RegExp®这个运算中,由于RegExp()构造器又会隐式地将r从任何类型转换为字符串类型,因而在这整个过程中,向原始的r参数传入任何值都不会产生任何的异常。

隐式转换导致的“潜规则”很大程度上增加了理解用户代码的难度,也不利于引擎实现。因 此,ECMAScript 在后期就倾向于抛弃这种做法,多数的“新方法”在发现类型不匹配的时 候,都设计为显式地抛出类型错误。一个典型的结果就是,在 ECMAScript 3 的时代, TypeError 这个词在规范中出现的次数是 24 次;到了 ECMAScript 5,是 114 次;而 ECMAScript 6 开始就暴增到 419 次。

因此,越是早期的特性,越是更多地采用了带有“潜规则”的隐式转换规则。然而很不幸的 是,几乎所有的“运算符”,以及大多数常用的原型方法,都是“早期的特性”。 所以在类型转换方面,JavaScript 成了“潜规则”最多的语言之一。

消化一下

到现在为止,这一节课其实才开了个头,也就是对“a + b”这个标题做了一个题解而已。 这主要是因为在 JavaScript 中有关类型处理的背景信息太多、太复杂,而且还处在不停的变化之中。许多稍早的信息,与现在的应用环境中的现状,或者你手边可备查的资料之间都存在着不可调和的矛盾冲突,因此对这些东西加以梳理还原,实在是大有必要的。这也就是为什么会写到现在,仍然没有切入正题的原因。

你至少应该知道这些:

  • 语言中的引用类型和值类型,以及 ECMAScript 中的原始值类型(Primitive values)之间存在区别;
  • 语言中的所谓“引用类型”,与 ECMAScript 中的“引用(规范类型)”是完全不同的概念;
  • 所有值通过包装类转换成对象时,这个对象会具有一个内部槽,早期它统一称为 [[PrimitiveValue]],而后来 JavaScript 为每种包装类创建了一个专属的;使用 typeof(x) 来检查 x 的数据类型,在 JavaScript 代码中是常用而有效方法;
  • 原则上来说,系统只处理 boolean/string/number 三种值类型(bigint 可以理解为 number 的特殊实现),其中 boolean 与其他值类型的转换是按对照表来处理的。

总的来说,类型在 JavaScript 中的显式转换是比较容易处理的,而标题“a + b”其实包含了太多隐式转换的可能性,因此尤其复杂。关于这些细节,下一篇再说。

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

这篇关于手把手教你创建第一个React Native自动化测试工具Detox的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/199197

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

Maven创建项目中的groupId, artifactId, 和 version的意思

文章目录 groupIdartifactIdversionname groupId 定义:groupId 是 Maven 项目坐标的第一个部分,它通常表示项目的组织或公司的域名反转写法。例如,如果你为公司 example.com 开发软件,groupId 可能是 com.example。作用:groupId 被用来组织和分组相关的 Maven artifacts,这样可以避免

如何使用Ansible实现CI/CD流水线的自动化

如何使用Ansible实现CI/CD流水线的自动化 持续集成(CI)和持续交付(CD)是现代软件开发过程中的核心实践,它们帮助团队更快地交付高质量的软件。Ansible,作为一个强大的自动化工具,可以在CI/CD流水线中发挥关键作用。本文将详细介绍如何使用Ansible实现CI/CD流水线的自动化,包括设计流水线的结构、配置管理、自动化测试、部署、以及集成Ansible与CI/CD工具(如Jen

批处理以当前时间为文件名创建文件

批处理以当前时间为文件名创建文件 批处理创建空文件 有时候,需要创建以当前时间命名的文件,手动输入当然可以,但是有更省心的方法吗? 假设我是 windows 操作系统,打开命令行。 输入以下命令试试: echo %date:~0,4%_%date:~5,2%_%date:~8,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% 输出类似: 2019_06