亢奋猫 发布的文章

我们知道做深拷贝的时候可以使用递归的方式也可以用 JSON.stringify + JSON.parse 这种看起来简单的方式。
那么 JSON.stringify + JSON.parse 这种方式真的好用吗?

我的经验告诉我:

JSON.stringify + JSON.parse 做深拷贝不安全,而且在大数据量的情况下存在性能问题,不推荐使用

下面我们主要围绕不安全的问题进行讨论,对于性能的问题简单提下。

为何不安全

不安全主要体现在两个方面:

  1. 拷贝过程中数据失真、丢失
  2. 处理特殊数据时候报错

数据失真、丢失

数据失真,丢失主要在这几种类型中有体现

Date对象拷贝后数据类型变成字符串

let obj = {
    d: new Date(),
};
console.log(JSON.parse(JSON.stringify(obj)));
// {d: "2020-08-12T04:47:40.958Z"}

正则对象、Error对象拷贝后变成空对象

let obj = {
    r: /\d+/gi,
    e: new Error('an error')
};
console.log(JSON.parse(JSON.stringify(obj)));
// {r: {}, e: {}}

对象里面的函数和undefined属性拷贝后属性丢失

let obj = {
    f: console.log,
    u: undefined
};
console.log(JSON.parse(JSON.stringify(obj)));
// {}

NaN、Infinity、-Infinity拷贝后变为null

let obj = {
    i: Infinity,
    l: -Infinity,
    n: NaN,

};
console.log(JSON.parse(JSON.stringify(obj)));
// {i: null, l: null, n: null}

改变对象的原型链

如果,对象的某个属性是由构造函数生成的,那么在拷贝后,他的 constructor 会指向 Object

var A = function () {
    this.a = 'a';
};
var a = new A();
var b = JSON.parse(JSON.stringify(a));
console.log(a.constructor, b.constructor);
// ƒ () {this.a = 'a'} ƒ Object() { [native code] }

特殊数据报错

这个简单的说就是如果对象中有环的话话就会报错,最简单的例子就是

console.log(JSON.parse(JSON.stringify(window)));

这个就会报错,所以在使用这种方式做深拷贝的时候也要注意环的问题。

为何性能差

关于性能的问题我这里不多说,推荐《如何提升JSON.stringify()的性能》这篇文章,这篇文章对JSON.stringify的性能问题说的很清晰,我也很认同。

参考文档

JSON.stringify深拷贝的缺点
如何提升JSON.stringify()的性能

应用举例

比如 AutoCAD、GoogleEarth、Unity、Unreal、PSPDKit、WebPack 等等。拿其中几个来简单说一下。

AutoCAD

这是一个用于画图的软件,在很长的一段时间是没有 Web 的版本的,原因有两个,其一,是 Web 的性能的确不能满足他们的需求。其二,在 WebAssembly 没有面世之前,AutoCAD 是用 C++ 实现的,要将其搬到 Web 上,就意味着要重写他们所有的代码,这代价十分的巨大。

而在 WebAssembly 面世之后,AutoCAD 得以利用编译器,将其沉淀了 30 多年的代码直接编译成 WebAssembly,同时性能基于之前的普通 Web 应用得到了很大的提升。正是这些原因,得以让 AutoCAD 将其应用从 Desktop 搬到 Web 中。

Google Earth

Google Earth 也就是谷歌地球,因为需要展示很多 3D 的图像,对性能要求十分高,所以采取了一些 Native 的技术。最初的时候就连 Google Chrome 浏览器都不支持 Web 的版本,需要单独下载 Google Earth 的 Destop 应用。而在 WebAssembly 之后呢,谷歌地球推出了 Web 的版本。而据说下一个可以运行谷歌地球的浏览器是 FireFox。

Unity 和 Unreal 游戏引擎

这里给两个油管的链接自己体验一下。

Unity WebGL 的戳这里:
https://youtu.be/rIyIlATjNcE
Unreal 引擎的戳这里:
https://www.youtube.com/watch?v=TwuIRcpeUWE

什么时候使用 WebAssembly?

说了这么多,我到底什么时候该使用它呢?总结下来,大部分情况分两个点。

对性能有很高要求的 App/Module/ 游戏。
在 Web 中使用 C/C++/Rust/Go 的库举个简单的例子。如果你要实现的 Web 版本的 Ins 或者 Facebook, 你想要提高效率。那么就可以把其中对图片进行压缩、解压缩、处理的工具,用 C++ 实现,然后再编译回 WebAssembly。

a70d0081607081471df4db435641b51a.jpg

如何描述一个Web应用的性能模型,简单来说,应该是 PV(PageView) + RT(Response
Time)。一般我们经常会看到一些网站发布数据说,我们的网站一天的PV是多少多少,这其实就就是一个很直观的性能数据。

PV 其实说的就是业务量:你的系统在可接受的 RT 内,所承受的 PV 就是系统的处理能力;当然我们更关注的是单位时间内的 PV,比如每秒的
PV,这代表你系统所能承受的并发能力;

我一贯的观点是,压力测试更多的是发现潜在的问题,其实没有办法告诉你他能支撑多大的业务量;这其中主要的问题在于业务的快速变化和用户行为的不可预知。增加服务器一般就是处理能力不够了,比如
cpu 繁忙,io 繁忙;

当然很多时候,业务系统的扩展性决定了你的应用是不是能通过增加服务器的方式提高处理能力;更多的是要找到问题,对症下药。

下面介绍两款免费的压力测试软件:

ab

ab 测试工具是 Apache 提供的一款测试工具,具有简单易上手的特点,在测试 Web 服务时非常实用。

ab 可以在 Windows 系统中使用,也可以在 Linux 系统中使用。这里我说下在 Linux 系统中的安装方法,非常简单,只需要在 Linux 系统中输入 yum-y install httpd-tools 命令,就可以了。

安装成功后,输入 ab 命令,可以看到以下提示:

ab.jpg

ab 工具用来测试 post get 接口请求非常便捷,可以通过参数指定请求数、并发数、请求参数等。

例如,一个测试并发用户数为 10、请求数量为 100 的的 post 请求输入如下:

ab -n 100  -c 10 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://test.api.com/test/register'

post.txt 为存放 post 参数的文档,存储格式如下:

usernanme=test&password=test&sex=1

附上几个常用参数的含义:

-n:总请求次数(最小默认为 1);
-c:并发次数(最小默认为 1 且不能大于总请求次数,例如:10 个请求,10 个并发,实际就是 1 人请求 1 次);
-p:post 参数文档路径(-p 和 -T 参数要配合使用);
-T:header 头内容类型(此处切记是大写英文字母 T)。

当我们测试一个 get 请求接口时,可以直接在链接的后面带上请求的参数:

ab -c 10 -n 100 http://www.test.api.com/test/login?userName=test&password=test

输出中,有几项性能指标可以提供给我们参考使用:

  • Requests per second:吞吐率,指某个并发用户数下单位时间内处理的请求数;
  • Time per request:上面的是用户平均请求等待时间,指处理完成所有请求数所花费的时间 /(总请求数 / 并发用户数);
  • Time per request:下面的是服务器平均请求处理时间,指处理完成所有请求数所花费的时间 / 总请求数;
  • Percentage of the requests served within a certain time:每秒请求时间分布情况,指在整个请求中,每个请求的时间长度的分布情况,例如有 50% 的请求响应在 8ms 内,66% 的请求响应在 10ms 内,说明有 16% 的请求在 8ms~10ms 之间。

JMeter

6ffe85677e50bb75152d45526a7ba667.png

该工具使用方法很多地方都有介绍,此处不在赘述。

使用方法:https://zhuanlan.zhihu.com/p/36526346
官网:https://jmeter.apache.org/

个人感觉,React 就像王者荣耀里的露娜,上手不容易,玩好更难,但上限很高,真的玩好了会非常秀。
Vue 就有点像亚瑟,上手容易,但上限不高,即使再熟练,也搞不出太秀的操作。

从团队角度:

  • 团队技术水平高,代码规范,用 React 更灵活。
  • 团队技术水平一般,用 Vue 更保险,出 bug 几率低点,也不容易写出很难维护的代码。

从个人角度:

  • 使用 React 的同时也是在加深自己对编程、函数式等等概念的理解,提升思考能力。慢慢的会有所积累和成长。
  • 而使用 Vue 一般能更快完成任务。但是个人感觉在技术方面的成长有限。

通过使用该工具我们可以轻松调试iOS或macOS的系统推送,我们只需要准备一个证书,准备设备token,就可以直接和 apns 通信并发送推送信息。通常我们可以用次工具判断证书是否正确配置。

Pusher

OS X and iOS application and framework to play with the Apple Push Notification service (APNs)

osx1.png

什么是注解 (Annotation)

注解其实就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相对应的处理。

为什么要用注解

注解可以给类、方法上注入信息。

常见注解

java.lang包下存在着5个基本的Annotation,其中有2个Annotation我们是非常常见的了。

@Overried

@Overried是告诉编译器要检查该方法是实现父类的,可以帮我们避免一些低级的错误。

比如当我们写了@Overried之后,我们在实现equals()方法的时候,把euqals()打错了,那么编译器就会发现该方法并不是实现父类的,于是就会给予错误。

@Deprecated

该注解也非常常见,Java在设计的时候,可能觉得某些方法设计得不好,为了兼容以前的程序,是不能直接把它抛弃的,于是就设置它为过时。

自定义注解

我们自定义的注解是可以带成员变量的,定义带成员变量的注解叫做元数据Annotation

public @interface MyAnnotation {
    String username();
}

使用注解

// 注解拥有什么属性,在修饰的时候就要给出相对应的值
@MyAnnotation(username = "kangfenmao")
public void add() {}

读取注解

@MyAnnotation(username = "kangfenmao")
public void add() {
  MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
  String username = annotation.username();
}

总结

注入对象的步骤:

  1. 得到想要注入的对象属性
  2. 通过属性得到注解的信息
  3. 通过属性的写方法将注解的信息注入到对象上
  4. 最后将对象赋给类。

注解其实就是两个作用:

  1. 让编译器检查代码
  2. 将数据注入到方法、成员变量、类上

如果没有响应注解内容,注解可以说是没有实用价值。让注解真正发挥作用,主要就在于注解处理方法。

JDK 常用注解

  1. 基本 Annotation 在 lang 包下,用于常用于标记该方法,抑制编译器警告等
  2. 元 Annotaion 在 annotaion 包下,常用于修饰其他的 Annotation 定义

升级 macOS 10.15.6 后,发现 php 版本号已经升级到了 php7.3

运行 php -v

PHP 7.3.11 (cli) (built: Jun  5 2020 23:50:40) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies

问题

但是比较坑的是默认没有安装 zip 扩展,而 Laravel 是需要 ext-zip 扩展包的:

composer global require laravel/installer

QQ20200901-170526@2x.png

brew 安装 [email protected]

brew update
brew install [email protected]
brew link [email protected] --force

必须要使用 force

编译安装 [email protected]

本文不再展开,参考这篇文章:https://segmentfault.com/a/1190000022699382

查考资料

discussions.apple.com
install-ext-zip-for-mac