JavaScript和TypeScript:你需要了解的关键差异
作者:京东零售 杨冰
译自Radix网站的文章,原文链接:radixweb.com/blog/typesc… Raval
正在寻找经验丰富的 JavaScript 开发团队来将您的应用创意变为现实?作为一名开发人员,如果您有机会参与 Web 开发项目,您一定了解 JavaScript 的工作原理。JavaScript 上市多年,已成为开发者社区中流行的脚本语言。
但正如我们所知,如果一种技术或语言正在崛起,总会有另一种选择进入市场并与领先者展开激烈竞争。这里有一个新的竞争对手 ——TypeScript。随着 TypeScript 的日益普及,我们可以将其视为具有额外功能的 JavaScript 增强版。
谈到 TypeScript,它是一种用于开发大型复杂应用程序的开源编程语言。TypeScript 由科技巨头之一——微软——于 2012 年开发,其创建背后的真正原因是处理大型应用程序。
此外,Angular 还使用 TypeScript 进行 Web 开发服务。根据这项研究,TypeScript 和 JavaScript 分别是开发人员希望使用的第二和第三大流行语言。你知道为什么吗?
实际上,JavaScript 被认为是应用程序和网页的主要脚本语言。因此,现在,我们可以将 JavaScript 用于TezJS 、React等前端框架,以及 Node.Js 和 Deno 框架的后端。
但现在真正的问题是,JavaScript 是为创建大型复杂的 Web 应用程序而开发的吗?我想答案是否定的!
在本文中,我们将比较这两种编程语言——TypeScript 与 JavaScript,它们之间的关系,它们的区别,并概述每种语言的优点。
但在此之前,在此视频中快速了解 TypeScript 和 JavaScript 之间的差异。
TypeScript 与 JavaScript:真正的区别
如果我们同时考虑两者——TypeScript 与 JavaScript,那么每个 JavaScript 代码在 TypeScript 中都是有效的。这意味着 TypeScript 是 JavaScript 的超集。
换句话说,我们可以说,
JavaScript + 更多功能 = TypeScript
因此,如果您将 JavaScript 编程文件 (.js) 保存为 TypeScript (.ts) 扩展名,它将执行得非常好。但这并不意味着这两种语言——TypeScript 和 JavaScript 是一样的。
因此,在进一步深入之前,让我们先了解一下每种语言的基本定义。以下是来自 Google Trends 的数据,显示了这两种前端语言过去一年的搜索趋势。
为什么在有 JavaScript 的情况下开发 TypeScript?
JavaScript 语言是作为客户端编程语言引入的。但是随着 JavaScript 在 Web 开发中的使用,开发人员了解到它也可以被视为一种服务器端编程语言。
然而,JavaScript 代码也变得相当复杂和沉重。因此,JavaScript 无法满足面向对象编程语言的期望。因此,JavaScript 永远不会作为服务器端技术在业界蓬勃发展。这就是为什么 TypeScript 语言诞生来弥合这一差距的原因。
什么是TypeScript?
如果被问到“什么比 JavaScript 更好?”,您一定会得到答案——TypeScript。
TypeScript 由 Microsoft 开发和维护,是一种面向对象的开源编程语言。它是 JavaScript 的超集,包含可选类型。此外,它还可以编译为纯 JavaScript。
简而言之,TypeScript 是一种静态编译的编程语言,用于编写清晰简洁的 JavaScript 代码。它实现与 JavaScript 相同的目的,可用于客户端和服务器端应用程序。此外,JavaScript 的库也兼容 TypeScript。
TypeScript 是一种同时支持动态类型和静态类型的编程语言。它提供类、可见性范围、命名空间、继承、联合、接口和许多其他特性。此外,它还提供注释、变量、语句、表达式、模块和函数。
您可以在 Node.Js 或任何其他支持 ECMAScript 3 或其最新版本的浏览器上执行它。
由于 TypeScript 是 JavaScript 的增强版本,因此 JavaScript 的所有代码在语法上都是有效的 TypeScript。但是,这并不意味着 TypeScript 编译器可以处理所有 JavaScript:
let a = 'a'; a = 1; // throws: error TS2322: Type '1' is not assignable to type 'string'.
TypeScript 提供的文件可以包含来自当前目标文件的类型数据,类似于 C++ 头文件如何定义当前目标文件的创建。因此,其他应用程序可以使用文件中定义的值,就像使用静态类型值的 TypeScript 实体一样。
您还会找到流行库(如 jQuery、D3.js 和 MongoDB)的第三方头文件。还有用于 NodeJs 基本模块的 TypeScript 标头,允许在 TypeScript 中进行 Node.Js 开发。
TypeScript 的编译器是在 JavaScript 中组装并用 TypeScript 编写的。它在 Apache License 2.0 下注册。
看完 TypeScript 介绍后,您一定想知道将静态类型添加到 JavaScript 的目的是什么?
好吧,我们可以用给定的陈述来澄清你的疑虑:
- 您可以避免隐藏忍者错误,例如经典的“未定义”不是函数。
- 易于重构代码而不会显着破坏它。
- 在大规模、复杂的系统中定位自己不再是一场噩梦。
根据这项研究,TypeScript 识别出大约 15% 的 JavaScript 错误。
动态类型的*性经常导致错误,这不仅降低了开发人员的效率,而且由于添加新代码行的开销增加而使开发变得很费劲。
因此,由于缺乏类型和编译时错误检查,JavaScript 对于组织和大型代码库中的服务器端代码来说是一个糟糕的选择。
正如他们的标语所暗示的那样,TypeScript 是可扩展的 JavaScript。
为什么我们需要使用 TypeScript?
正如我们之前所说,TypeScript 是 JavaScript 的增强版。因此,在将它与 CoffeeScript(添加了语法糖)或 PureScript(与 JavaScript 完全不相似)等其他语言进行比较时,编写 TypeScript 代码需要学习很多东西。
在 TypeScript 中,类型是可选的,任何 JavaScript 文件都是有效的 TypeScript 文件。虽然如果您的任何初始文件存在类型问题,编译器会通知您,但它仍会提供一个有效的 JavaScript 文件。TypeScript 将不负众望,随着时间的推移提高您的技能也很简单。
TypeScript 适合前端还是后端?
由于 TypeScript 被编译为 JavaScript,因此它适用于应用程序开发的前端和后端。
此外,JavaScript 是网页和应用程序前端的首选编程语言。因此,出于同样的原因,可能会使用 TypeScript,但它在服务器端也适用于复杂的大型企业项目。
但是,您也可以使用其他*前端框架(如 React、Angular、Vue)来构建下一代应用程序。
TypeScript 的类型
TypeScript 包含各种基本类型,例如 Number、Array、Tuple、Boolean、String 等等。好吧,其中一些类型在 JavaScript 中不可用。但是,您可以在TypeScript 文档中了解有关它们的更多信息。
此外,下面是一些其他类型,它们是 TypeScript 的表现力:
Any & Unknown
一个名为 Any(任何你想要的)的类型可以覆盖 unknown 是它的类型安全系统。在这里,any 允许您在想要转义类型系统时分配和 JavaScript 变量。它广泛用于描述尚未验证且类型未知的传入变量(例如,来自第三方 API)。
Unknown 类似于 Any,但它不允许您对它执行任何操作,除非它已明确进行类型检查。
Void
当没有返回值时,使用 Void。一般用于不返回任何函数的返回类型。
Never
Never 是不应该发生的事情的返回类型,例如异常抛出函数。
Intersection & Union Types(交集和并集类型)
这些类型允许您根据逻辑创建自定义类型。
交集类型让您可以将几种基本类型组合成一种类型。例如,如果我们创建一个自定义类型 Person,它包含first_name:string
一个last_name:string
. 好吧,你可以这样说:我希望我的类型是这样且那样的。
联合类型允许您输入各种基本类型之一。例如,如果有一个返回result:string
or undefined
,您可以这样说:我希望我的类型是这个或那个。
当您将它们视为空间时,所有这些类型都有意义。
TypeScript 同时支持隐式和显式类型。如果您不显式编写类型,编译器将启用类型推断来识别您正在使用的类型。
另一方面,明确编写它们会带来好处,例如协助其他团队成员阅读您的代码并验证您所看到的是编译器所看到的。
TypeScript 的特点
借助 TypeScript 的高级特性,它支持 JavaScript 的附加特性,例如面向对象的编程概念、JS 库、平台无关性等。
Compatibility(兼容性)
TypeScript 也支持旧的和新的附加功能。但是,它兼容所有版本的 JavaScript,例如 ES7 和 ES12。它可以将 ES7 中的完整代码编译回 ES5,反之亦然。这确保了平稳过渡和语言可移植性。
Static Typing(静态类型)
静态类型意味着开发人员必须声明变量类型。
假设我们取变量名 str。代码将不会运行,直到您给它一个类型,例如 Integer、Float、List 或任何其他类型。而 TypeScript 是静态类型的。
静态类型可以帮助您及早检测错误、更快地完成代码等等。
现在,让我们在这里为您提供其他突出的特点:
- 它易于维护并可提高项目生产力。
- 可以使用静态类型和注释
- 支持面向对象的特性,例如接口、继承和类
- 调试简单,问题及早发现。
- 支持 ES6 (ECMAScript),它为处理对象和继承提供了更简单的语法。
- 全功能 IDE 支持
TypeScript 的优点
TypeScript 提供了多种优势,可以帮助您为 Web 开发编写更好的编程语言。
Language Features(语言特性)
以下是 TypeScript 支持的其他功能。
- 命名空间
- 接口
- 空检查
- 泛型
- 访问修饰符
Optional Parameters(可选参数)
// -- TypeScript -- //
function log(message: string = null) { }
// -- TypeScript compiled output -- //
function log(message) {
if (message === void 0) { message = null; }
}
// -- JavaScript with Babel -- //
function Log(message = null) { }
// -- Babel compiled output -- //
"use strict";
function Log() {
var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
}
Classes Class方式
// -- TypeScript -- //
class Article {
name: string;
constructor(name: string) {
this.name = name;
}
}
// -- TypeScript compiled output -- //
var Article = /** @class */ (function () {
function Article(name) {
this.name = name;
}
return Article;
}());
// -- JavaScript with Babel -- //
class Article {
constructor(name) {
this.name = name;
}
}
// -- Babel compiled output -- //
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Article = function Article(name) {
_classCallCheck(this, Article);
this.name = name;
};
什么是 JavaScript?
JavaScript – 一种脚本语言,用于开发交互式网页。它遵守客户端编程规则;因此,它可以在用户的网络浏览器中无缝执行。但是,您可以将 JavaScript 与其他技术(如 XML 和 REST API)结合使用。
JS 的主要目的是使其成为一种互补的脚本语言,类似于 Visual Basic 之于 C++。但是,JavaScript 不适合大型复杂应用程序。它旨在为一个应用程序只编写几百行代码。
以下是 JavaScript 提供的一些独特功能:
- 灵活、动态和跨平台
- 它可以用于客户端和服务器端
- 轻量化解读
- 所有浏览器都支持
- 弱类型
- 即时编译
TypeScript 和 JavaScript 之间的区别
TypeScript 和 JavaScript 之间的区别
在比较两种编程语言——TypeScript 和 JavaScript 时,我们必须考虑许多因素,如下所示:
1) 学习曲线
TypeScript 是 JavaScript 的超集。要编写 TypeScript 代码,您应该对 JavaScript 有基本的了解和知识。此外,您还应该清楚 OOPS 的概念。
另一方面,JavaScript 是一种流行且易于学习的脚本语言。许多开发人员将 JavaScript 与 CSS 和 HTML 结合使用来创建 Web 应用程序。然而,HTML 很难,因为它包含事件处理、Web 行为、动画和脚本。
2)开发者社区
TypeScript 在短时间内流行起来,并被许多企业实施。您会在 Internet 上找到许多学习 TypeScript 的教程和指南。但是,它有一个非常活跃和支持的社区。
另一方面,与 TypeScript 相比,JavaScript 没有庞大的社区。JavaScript 提供了许多库、框架和代码实践。因此,建议您了解最适合您的业务需求的Web 开发团队结构,以获得整体团队绩效。
3)性能
众所周知,创建 TypeScript 是为了克服 JavaScript 对大型复杂应用程序的挑战。因此,TypeScript 节省了开发时间并让开发人员变得更有效率。
TypeScript 和 JavaScript 之间的唯一区别是 TypeScript 代码在执行之前被编译成 JavaScript。
4) 语法
TypeScript 提供了 JavaScript 不提供的变量声明、函数范式和类型系统。它在语法方面类似于 JScript 和 .Net,支持 ECMAScript 2015 标准功能,包括模块、箭头函数语法和类。
JavaScript 也遵循 ECMAScript 定义。但是,它不是像 TypeScript 这样的类型化语言。它使用许多来自 C 语言的结构化编程术语,例如 if 语句、switch 语句、do-while 循环等等。它提供事件驱动风格、函数式和命令式编程。
5)工具和框架
由于微软支持 TypeScript,它拥有许多领先的框架和编辑器。通过与编辑器的紧密集成,它提供了编译期间的错误处理,以避免在运行时出错。
另一方面,市场上有许多JavaScript 框架可用于 Web 开发项目需求。这是一个非常受程序员欢迎的巨大生态系统。您可以快速找到精通 ReactJS、VueJS、Angular 和其他框架的开发人员。
6)代码
对于TypeScript:
class Person
{
private name: string;
constructor (private name: string)
{
this.name = name;
}
name()
{
return “name is “ + this.name;
}
}
对于 JavaScript:
var Person = (function()
{
function Person(personName)
{
this.name = personName;
}
Person.prototype.name= function()
{
return "My name is " + this.name;
}
return Person;
})();
TypeScript 与 JavaScript 有何不同?
我们知道 TypeScript 提供的功能比 JavaScript 多。简而言之,TypeScript 是一种面向对象的编程语言,而 JavaScript 是一种脚本语言。因此,TypeScript 通过 ES6 特性提供接口和模块;另一方面,JavaScript 不提供此类功能。
实际上,一些开发人员可能会混淆面向对象和函数式编程语言。但是,您可以在这里区分函数式编程与面向对象的编程语言,并了解它们之间的区别。
为什么要将您的项目迁移到 TypeScript?
如果您有一个庞大而复杂的代码库,则发生错误的可能性更高。但是,如果能在编译期间解决了一些错误,那就太好了。这时你可以使用 TypeScript 来减少编译时的错误。最好的部分是完整的 Java (此处应该是作者笔误,应该是JavaScript)代码库可以按原样重用。
何时选择:JavaScript 和 TypeScript 的区别
TypeScript
编译时类型检查 | 使用 Vanilla JavaScript,类型验证在运行时执行。然而,这会增加运行时开销,这可以通过进行编译时验证来避免。 |
大型项目或多个开发人员 | TypeScript 可以在大型项目或许多开发人员一起工作时无缝运行。 |
易于使用新库或框架 | 假设,如果你正在使用 React 进行开发并且不熟悉它的 API,你可以获得 语法提示来帮助你识别和导航新界面。但是,它们都提供类型定义 |
JavaScript
小项目 | 对于代码较少的小型项目,TypeScript 可能有点矫枉过正。 |
框架支持 | 如果 TypeScript 不支持您选择的框架 – 例如EmberJS,那么您可能无法利用它的功能。 |
构建工具 | 要生成能运行的最终 JavaScript,TypeScript 需要有一个构建的步骤。不过,在不使用任何构建工具的情况下开发 JavaScript 应用正变得越来越少。 |
测试工作流程 | 如果您优秀的 JavaScript 开发人员已经在使用测试驱动开发,那么切换到 TypeScript 的好处可能不足以证明迁移成本是合理的。 |
我应该学习 JavaScript 还是 TypeScript?
如果你了解 JavaScript,那么你就很容易理解 TypeScript。它们两种语言共享相同的语法和运行时行为。
作为最流行的语言,JavaScript 提供了许多资源和庞大的开发人员社区。由于两种语言在很多情况下都以相同的方式执行,因此TypeScript 开发人员也可以从这些资源中受益。
TypeScript 相对于 JavaScript 的优势
- TypeScript 支持静态类型。这意味着静态类型允许在构建时检查类型的准确性。
- 在开发时,TypeScript 会识别编译错误。因此,运行时评估错误的范围非常小。另一方面,JavaScript 是一种解释型语言。
- TypeScript 只是具有一些额外功能的 JS,即 ES6 功能。TS 编译器可以将 .ts 文件编译成 ECMAScript,尽管它可能不会保存在您选择的 Web 浏览器中。
TypeScript 会取代 JavaScript 吗?
那么,上述问题的最短答案是否定的!
在谈论 TypeScript 时,它是一种完全不同的语言,只是它继承了 JavaScript 的基本性质。因此,JavaScript 永远也不会被取代。
JavaScript 是软件开发行业中流行的基础技术之一,被大量开发人员用于客户端和服务器端。
另一方面,TypeScript 不直接在 Web 浏览器中执行。它转译为 JavaScript。JavaScript 更容易调试和编译,因为它直接在 Web 浏览器中执行。然而,TypeScript 并不是为所有类型的项目开发的。因此,两种编程语言都有其优点和缺点以及一组特征。为了顺应企业 Web 发展趋势,您必须采用新技术或框架来获得更好的业务流程和客户体验。
正面比较:TypeScript 与 JavaScript
TypeScript 和 JavaScript 在开发交互式网页方面有许多相似之处。在提供 TypeScript 与 JavaScript 的直接比较时,我们可以说 JavaScript 是一种轻量级的解释型动态语言,用于增强 HTML 网页。另一方面,TypeScript 是 JavaScript 的增强版。这意味着 TypeScript 是 JavaScript 和其他一些特性的组合。
- TypeScript是由 Microsoft Corporation 开发的一种面向对象的编程语言,而JavaScript是用于 Web 的编程语言。
- TypeScript是一种用于构建大型 Web 应用程序的开源语言,而JavaScript是一种有助于开发交互式网页的服务器端编程语言。
另一方面,TypeScript 是 JavaScript 的增强版。这意味着 TypeScript 是 JavaScript 和其他一些特性的组合。
让我们了解下表中 TypeScript 与 JavaScript 的重要区别。
范围 | Typescript | JavaScript |
---|---|---|
开发者 | Microsoft in 2012 | Brendan Eich (Netscape),1995 年 |
定义 | TypeScript 是一种强大的面向对象语言,作为 JavaScript 的超集,具有泛型和 JS 特性来解决 JS 的复杂问题。 | JavaScript 是一种脚本语言,具有创建动态网页的一流功能。 |
类型 | 强类型。TypeScript 支持静态类型和动态类型。 | 弱类型 。JavaScript 仅支持动态类型。 |
生态 | TypeScript 更像是一种支持静态类型的强大而直观的语言。 | JavaScript 是一种简单的语言,它优化了代码的兼容性,易于阅读和编写。 |
编译 | TypeScript 需要编译。 | JavaScript 不需要编译。 |
数据绑定 | TypeScript 利用接口和类型等概念来定义所使用的数据。 | JavaScript 中没有这样的概念。 |
学习曲线 | TypeScript 有一条不友好的学习曲线。此外,它需要JavaScript知识。 | 它易于学习并且是一种用于编写 Web 脚本的灵活语言。 |
Npm 包 | 使用Typescript,许多npm包要么有静态类型定义,要么有一个更容易安装的外部类型定义。 | JavaScript提供了不需要任何构建步骤就可以搜索和生成代码的替代方案。 |
客户端或服务器端 | TypeScript 专门用于客户端。 | JavaScript 用于服务器端和客户端。 |
文件扩展名 | .tsx 和 .ts | .js |
社区 | TypeScript 有一个较小的软件开发者社区。 | JavaScript 拥有庞大的软件开发人员社区。 |
原型设计 | 原型设计特性在 TypeScript 中可用。 | JS 不支持原型设计。 |
公司和网站 | Asana, Clever, Screen award | Airbnb、Codecademy、Instagram |
代码示例 | function multiply (a, b){ return a*b;}var result = multiply(a, b);console.log('答案是 - ' + result); |
<script>function multiply (a, b){ return a*b;}var result = multiply(a, b);document.write (‘The answer is – ’ + result);</script> |
结论
最后,在阅读了我们在本文中整理的所有见解之后,我们可以说这两种语言各有利弊。
TypeScript 适合想要创建整洁干净的可读代码的开发人员。好吧,我们没有提到 TypeScript 提供了什么,包括各种实时错误检查和静态类型。
虽然 JavaScript 不是一种综合性的编程语言,但它可以与 HTML 一起使用来提高网页的质量。甚至,您会发现许多精通 JavaScript 编码的经验丰富的开发人员。
但是,与 JavaScript 一样,并非所有 Web 浏览器都支持 TypeScript。所以,如果你在 TypeScript 和 JavaScript 之间纠结,可以参考上面的文章。
初次翻译,个人水平有限,有翻译不恰当的地方欢迎大佬们指正。
推荐阅读
-
epoll简介及触发模式(accept、read、send)-epoll的简单介绍 epoll在LT和ET模式下的读写方式 一、epoll的接口非常简单,一共就三个函数:1. int epoll_create(int size);创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close关闭,否则可能导致fd被耗尽。2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);epoll的事件注册函数,它不同与select是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create的返回值,第二个参数表示动作,用三个宏来表示:EPOLL_CTL_ADD:注册新的fd到epfd中;EPOLL_CTL_MOD:修改已经注册的fd的监听事件;EPOLL_CTL_DEL:从epfd中删除一个fd;第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:struct epoll_event { __uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */};events可以是以下几个宏的集合:EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭); EPOLLIN事件:EPOLLIN事件则只有当对端有数据写入时才会触发,所以触发一次后需要不断读取所有数据直到读完EAGAIN为止。否则剩下的数据只有在下次对端有写入时才能一起取出来了。现在明白为什么说epoll必须要求异步socket了吧?如果同步socket,而且要求读完所有数据,那么最终就会在堵死在阻塞里。 EPOLLOUT:表示对应的文件描述符可以写; EPOLLOUT事件:EPOLLOUT事件只有在连接时触发一次,表示可写,其他时候想要触发,那要先准备好下面条件:1.某次write,写满了发送缓冲区,返回错误码为EAGAIN。2.对端读取了一些数据,又重新可写了,此时会触发EPOLLOUT。简单地说:EPOLLOUT事件只有在不可写到可写的转变时刻,才会触发一次,所以叫边缘触发,这叫法没错的!其实,如果真的想强制触发一次,也是有办法的,直接调用epoll_ctl重新设置一下event就可以了,event跟原来的设置一模一样都行(但必须包含EPOLLOUT),关键是重新设置,就会马上触发一次EPOLLOUT事件。1. 缓冲区由满变空.2.同时注册EPOLLIN | EPOLLOUT事件,也会触发一次EPOLLOUT事件这个两个也会触发EPOLLOUT事件 EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);EPOLLERR:表示对应的文件描述符发生错误;EPOLLHUP:表示对应的文件描述符被挂断;EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);等待事件的产生,类似于select调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。-------------------------------------------------------------------------------------------- 从man手册中,得到ET和LT的具体描述如下EPOLL事件有两种模型:Edge Triggered (ET)Level Triggered (LT)假如有这样一个例子:1. 我们已经把一个用来从管道中读取数据的文件句柄(RFD)添加到epoll描述符2. 这个时候从管道的另一端被写入了2KB的数据3. 调用epoll_wait(2),并且它会返回RFD,说明它已经准备好读取操作4. 然后我们读取了1KB的数据5. 调用epoll_wait(2)......Edge Triggered 工作模式:如果我们在第1步将RFD添加到epoll描述符的时候使用了EPOLLET标志,那么在第5步调用epoll_wait(2)之后将有可能会挂起,因为剩余的数据还存在于文件的输入缓冲区内,而且数据发出端还在等待一个针对已经发出数据的反馈信息。只有在监视的文件句柄上发生了某个事件的时候 ET 工作模式才会汇报事件。因此在第5步的时候,调用者可能会放弃等待仍在存在于文件输入缓冲区内的剩余数据。在上面的例子中,会有一个事件产生在RFD句柄上,因为在第2步执行了一个写操作,然后,事件将会在第3步被销毁。因为第4步的读取操作没有读空文件输入缓冲区内的数据,因此我们在第5步调用 epoll_wait(2)完成后,是否挂起是不确定的。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。最好以下面的方式调用ET模式的epoll接口,在后面会介绍避免可能的缺陷。 i 基于非阻塞文件句柄 ii 只有当read(2)或者write(2)返回EAGAIN时才需要挂起,等待。但这并不是说每次read时都需要循环读,直到读到产生一个EAGAIN才认为此次事件处理完成,当read返回的读到的数据长度小于请求的数据长度时,就可以确定此时缓冲中已没有数据了,也就可以认为此事读事件已处理完成。Level Triggered 工作模式相反的,以LT方式调用epoll接口的时候,它就相当于一个速度比较快的poll(2),并且无论后面的数据是否被使用,因此他们具有同样的职能。因为即使使用ET模式的epoll,在收到多个chunk的数据的时候仍然会产生多个事件。调用者可以设定EPOLLONESHOT标志,在 epoll_wait(2)收到事件后epoll会与事件关联的文件句柄从epoll描述符中禁止掉。因此当EPOLLONESHOT设定后,使用带有 EPOLL_CTL_MOD标志的epoll_ctl(2)处理文件句柄就成为调用者必须作的事情。然后详细解释ET, LT:LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表.ET(edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认(这句话不理解)。在许多测试中我们会看到如果没有大量的idle -connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当我们遇到大量的idle- connection(例如WAN环境中存在大量的慢速连接),就会发现epoll的效率大大高于select/poll。(未测试)另外,当使用epoll的ET模型来工作时,当产生了一个EPOLLIN事件后,读数据的时候需要考虑的是当recv返回的大小如果等于请求的大小,那么很有可能是缓冲区还有数据未读完,也意味着该次事件还没有处理完,所以还需要再次读取: 这里只是说明思路(参考《UNIX网络编程》) while(rs) {buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);if(buflen < 0){// 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读// 在这里就当作是该次事件已处理处.if(errno == EAGAIN)break; else return; }else if(buflen == 0) { // 这里表示对端的socket已正常关闭. } if(buflen == sizeof(buf) rs = 1; // 需要再次读取 else rs = 0; } 还有,假如发送端流量大于接收端的流量(意思是epoll所在的程序读比转发的socket要快),由于是非阻塞的socket,那么send函数虽然返回,但实际缓冲区的数据并未真正发给接收端,这样不断的读和发,当缓冲区满后会产生EAGAIN错误(参考man send),同时,不理会这次请求发送的数据.所以,需要封装socket_send的函数用来处理这种情况,该函数会尽量将数据写完再返回,返回-1表示出错。在socket_send内部,当写缓冲已满(send返回-1,且errno为EAGAIN),那么会等待后再重试.这种方式并不很完美,在理论上可能会长时间的阻塞在socket_send内部,但暂没有更好的办法. ssize_t socket_send(int sockfd, const char* buffer, size_t buflen) { ssize_t tmp; size_t total = buflen; const char *p = buffer; while(1) { tmp = send(sockfd, p, total, 0); if(tmp < 0) { // 当send收到信号时,可以继续写,但这里返回-1. if(errno == EINTR) return -1; // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满, // 在这里做延时后再重试. if(errno == EAGAIN) { usleep(1000); continue; } return -1; } if((size_t)tmp == total) return buflen; total -= tmp; p += tmp; } return tmp; } 二、epoll在LT和ET模式下的读写方式 在一个非阻塞的socket上调用read/write函数, 返回EAGAIN或者EWOULDBLOCK(注: EAGAIN就是EWOULDBLOCK) 从字面上看, 意思是: * EAGAIN: 再试一次 * EWOULDBLOCK: 如果这是一个阻塞socket, 操作将被block * perror输出: Resource temporarily unavailable 总结: 这个错误表示资源暂时不够, 可能read时, 读缓冲区没有数据, 或者, write时,写缓冲区满了 。 遇到这种情况, 如果是阻塞socket, read/write就要阻塞掉。 而如果是非阻塞socket, read/write立即返回-1, 同 时errno设置为EAGAIN. 所以, 对于阻塞socket, read/write返回-1代表网络出错了. 但对于非阻塞socket, read/write返回-1不一定网络真的出错了. 可能是Resource temporarily unavailable. 这时你应该再试, 直到Resource available. 综上, 对于non-blocking的socket, 正确的读写操作为: 读: 忽略掉errno = EAGAIN的错误, 下次继续读 写: 忽略掉errno = EAGAIN的错误, 下次继续写 对于select和epoll的LT模式, 这种读写方式是没有问题的. 但对于epoll的ET模式, 这种方式还有漏洞. epoll的两种模式 LT 和 ET
-
你需要了解的软件测试类型和常见感测 [经典长文
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
源码为您提供,零基础搭建的免费网址导航站--中国妖怪百集,收集了大量古代文献中的妖怪,非常详细的记录了妖怪的来历、描述甚至图片,让您对中国的妖怪文化有一个整体的了解,茶余饭后的消遣非常有趣,类似的网站还有很多,期待您的探索! 导航站的另一个特点是汇集了大量咖啡平时用的非常好的工具软件,其中大部分都是在线的,不需要下载安装,包括文档协作、分享,图片、音频、视频处理,格式转换,文件传输,各个网站的视频下载等等,兼职就是一个工具百宝箱! 如果你觉得这些网站不符合你的使用习惯,或者想添加一些自己收藏的网站,那么把源码交给你,只需简单修改就可以变成符合自己使用习惯的独特导航了! 如何修改 导航站采用纯静态构建,下载源代码后,只需要修改 html 文件中的代码块即可,代码块结构如下: 只需要修改四个地方,分别对应网站的四个关键信息: 修改相应网站的 URL 地址 修改相应网站的徽标 修改相应网站的名称
-
趣谈留言队列,搞清楚留言队列到底是什么!-说到消息队列,洪觉大概能猜到人们听到消息队列的反应,大致可以分为以下几类人。 第一类人,懵懵懂懂,刚上大学接触编程,还没用过消息队列,甚至还以为消息队列就是代码里面要新建一个List之类的;第二类人,听过消息队列,了解消息队列,但具体是什么还不是太明白,只知道一说到消息队列,脑海里马上出现了三组词,削峰、异步、解耦;第三类人,用过消息队列,对它有一定了解,但不知道为什么要这样设计,消息队列有什么样的前世今生,是如何演化到现在的模式的?**第四类人,已经对消息队列有了足够的了解,可以阅读本帖作为复习和温习。**你属于哪一类?无论你对消息队列了解多少,读完这篇文章后,我相信你都会有所收获。 什么是消息队列?我们为什么要使用消息队列?真的只是因为它看起来很勉强、很常用吗?当然不是,一项技术的出现往往是为了解决某种痛点,我们就从这个痛点出发,看看消息队列到底是为了解决什么问题而诞生的。 相信大家在工作之前,或者工作中接触单片机的次数会多一点,不管什么业务都一股脑塞进一个系统里,这种情况下接触消息队列的场景会比较少。但随着业务的增长,量上去了,单机系统就很难维护了,也扛不住并发量的增长,就需要把原来的单体应用拆分成多个服务。例如,牛奇网采用分布式架构,将原来的单体系统拆分成用户服务、题库服务、求职服务、论坛服务等,每个分布式节点都有一个集群,保证高可用性。 那虽然在这样的微服务架构下,如果某个核心业务并发量过大,系统就扛不住了。比如淘宝、淘票票、拼多多、京东等电商场景中的支付场景,你在某宝下单并支付后,调用支付服务,完成支付后,还需要更新订单的状态,这个时候就需要调用订单服务,那我们平时也下单,除了简单完成这些操作外,还会给你相应的积分;商家也会收到订单消息,并给您发送旺旺消息,确认订单无误;同时,也会给您发送消息,确认订单无误。确认订单无误;同时您还可以查看您的物流状态;还有系统为了给您推荐更适合您的商品,会根据您的订单做类似的推荐等等,我说的这些都是当我们下单后,肉眼可以感知到系统所做的动作。 **一个支付动作如果还需要调用那么多服务,等他们响应成功,最后再告诉用户你支付成功了,用户在系统中的整个体验会非常糟糕。**设想一下,假设请求服务+处理请求+响应总共需要 50ms,我们上面列出的场景:支付服务、订单服务、积分服务、商家服务、物流服务、推荐服务,总共需要 300ms。
-
关于MySQL中的隔离级别和事务,你需要了解什么?
-
41 个下载免费 3D 模型的最佳网站-使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 17. Clara.io Clara.io 是一个创建 3D 内容的全球平台,也是一个培养新 3D 艺术家的社区。Clara.io 提供+100,000个免费的3D模型,包括OBJ,Blend,STL,FBX,DAE,Babylon.JS,Three.JS格式,用于 Clara.io,Unity 3D,Blender,Sketchup,Cinema 4D,3DS Max和Maya。 使用说明:免费,标准和专业帐户仅供个人使用,如果您需要将 clara.io 用于商业用途,请与销售团队联系。 18. 3DExport 3DExport是一个市场,您可以在其中购买和销售用于CG项目的3D模型,3D打印模型和纹理。它提供15 +不同的3D格式供下载,如3DS MAX(.max),Cinema4D(.c4d),Maya(.mb,.ma),Lightwave(.lwo),Softimage(.xsi),Wavefront OBJ(.obj),Autodesk FBX(.fbx)等。它还提供15种不同的语言! 使用说明:免费下载仅供个人和非商业用途。 19. 3D Warehouse 3D Warehouse是一个开放的库,允许用户共享和下载SketchUp 3D模型,用于建筑,设计,施工和娱乐!任何人都可以免费制作,修改和重新上传内容到3D仓库,您可以找到任何您能想到的东西,如家具,电子产品,室内产品等。 使用说明:3D Warehouse中的所有模型都是免费的,因此任何人都可以下载文件以用于SketchUp甚至其他软件,如AutoCAD,Revit和ArchiCAD。 20. CadNav.com CadNav是CGI平面设计师和CAD / CAM / CAE工程师的在线3D模型库,我们提供超过50000 +免费3D模型和CAD模型下载。在CadNav网站上,您可以下载高质量的多边形网格3D模型,3D CAD实体对象,纹理,Vray材料,3D作品,CAD图纸等。 使用说明:免费下载仅供个人和非商业用途。 21. All3dfree.net 就像网站名称一样,它提供免费的3D模型,还包括Vray材料,CAD块,2d和3d纹理集合,无需注册即可免费下载。它是不断更新的,因此您可以查找或请求3DS,MAX,C4D,skp,OBJ,FBX,MTL等格式的模型。 使用说明:所有资源均不允许用于商业用途,否则您将承担责任。 22. Hum3D 自2005年以来,Hum3D帮助来自3多个国家的80D艺术家节省3D建模时间,并制作逼真的3D模型,用于电影,视频游戏,AR应用程序和可视化。所有模型均由首席3D艺术家进行验证,他们检查其是否符合专业要求和最新的3D建模标准。 使用说明:免费下载仅供个人和非商业用途。 23. Artist-3D.com 艺术家-3D 库存的免费 3D 模型下载按通用类别排序。它为人体解剖学、汽车、家具、火箭、卫星等模型提供 AutoDesk 3DS Max 格式。您还可以在浏览他们的网站时找到教程和类似类型的建模。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 24. Free the models 就像本网站的标题一样,它为3d应用程序和3d游戏引擎提供免费的内容模型。您可以为您的任何项目找到许多有趣且有用的模型!它提供3ds,wavefront,bryce,poser,lightwave,md2和unity3d格式的模型。还有一个很棒的纹理集合,可以在您最喜欢的建模和渲染程序中使用。 使用说明:您从这里下载的所有内容都可以免费使用,除非它不能包含在另一个免费的网络或CD收藏中,也不能单独出售。否则,您可以在商业游戏,3D应用程序或渲染作品中使用它。您不必提供信用,但如果您这样做,那就太好了。 25. Resources.blogscopia 本网站由一家名为Scopia的公司创建。他们制作3D图像和视频,您可以找到许多为CGI工作的信息架构设计的模型,所有这些都可以在现实生活中使用。您可以免费下载它们,但是,如果您想一次下载它们,您可以支付 3 到 9 欧元。 使用说明:您可以免费下载模型部分的所有文件。每个压缩文件都包含您也可以在此处找到的许可证。基本上,您可以对文件执行任何操作。唯一的限制是不归属于Scopia的重新分发。 26.ambientCG 1000+公共领域PBR材料适合所有人!环境CG是使用许多不同的方法和资产类型创建的,例如照片纹理(PBR),贴花(PBR),图集(PBR),照片纹理(普通),物质存档(SBSAR),雕刻画笔,3D模型和地形。您可以在所有项目中*使用它们! 使用说明:在 ambientCG 上提供下载的所有 PBR 材料、画笔、照片和 3D 模型均根据知识共享 CC0 1.0 通用许可提供。您可以复制、修改、分发和执行作品,即使是出于商业目的,也无需征得许可。信用将不胜感激。 不要满足于平庸的大理石纹理 - 立即使用我们的免费PBR大理石纹理升级您的3D设计。 27.Pixar One Twenty Eight 这是一个提供官方动画行业经典纹理的网站:皮克斯,创建于 1993 年,该纹理库包括 128 个重复纹理,现在免费提供。 它包含您来到的纹理,包括砖块和动物毛皮。肯定会有一些你可以使用的东西。 使用说明:皮克斯动画工作室的《Pixar One Twenty Eight》根据知识共享署名4.0国际许可协议进行许可。即使出于商业目的,您也可以重新混合、调整和构建您的作品,只要您以相同的条款对新创作进行信用和许可。 访问数以千计的免费纹理并提升您的设计游戏 - 立即开始下载! 28. 3DXO 即使有近 620 个免费贴纸可供下载,3DXO 也不是最大的资源,但它的内容非常有用,不需要注册。无论是简单的墙壁或地板,还是一些奇怪的小东西,您都需要的纹理都可以在此网站上看到。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 29. 3DModelsCC0 3DModelsCC0 与其他产品的不同之处在于它包含超过 250+ 个高质量 3D 模型,并且本网站上的所有内容都是免费的,完全是公共领域!使用我们的模型时无需信用或归属! 使用说明:为每个人提供完全免费的公共领域内容。 30.Sketch up texture club Sketchup Texture Club是一个非营利性的教育和信息门户网站,由3D社区的图像促进协会管理,特别强调面向学生和建筑和室内设计专业人士的可视化和渲染技术,以及所有正在学习3D可视化的人。 使用说明:您无需支付版税或使用费。纹理可以免费下载和使用。不允许将纹理作为竞争产品出售或重新分发,即使图像被修改也是如此。 31. FlippedNormals FlippedNormal 是一个提供计算机图形和 3D 资产的市场,您可以找到许多用于雕刻、建模、纹理、概念艺术、3D 模型、游戏资产或课程的高级资产! 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 32. NASA 3D NASA 3D网站是一个在线门户,提供与太空和各种NASA任务相关的大量三维模型和模拟。该网站是用户友好的,并提供有关每个型号的详细信息。该网站允许用户探索和下载几种不同格式的模型,包括 OBJ、STL 和 FBX,只需单击下载按钮即可。 使用说明: 要下载模型,只需单击模型页面上的下载按钮并选择所需的格式。 33. 3DAGOGO (Astroprint) 3DAGOGO 是一个提供广泛 3D 模型的网站,包括角色、车辆和建筑物。3DAGOGO 的独特功能之一是它专注于适合 3D 打印的模型,使其成为希望创建物理原型或模型的设计师的绝佳资源。要使用 3DAGOGO,设计师只需在网站上搜索他们正在寻找的模型类型,然后下载 STL 格式的文件。 使用说明: 要使用 3DAGOGO,只需搜索所需的 3D 模型类型并下载 STL 格式的文件。根据需要自定义模型,并确保在将其用于商业目的之前检查使用权限。 34. FreeCAD FreeCAD是一款了不起的3D建模软件,可让您在计算机上创建令人难以置信的3D设计。该软件可免费下载和使用,它提供了广泛的工具和功能,可用于创建用于各种目的的3D模型。 该网站易于浏览,您可以找到开始使用FreeCAD的所有必要信息。此外,该网站还提供一系列教程和指南,可帮助您了解 3D 建模的来龙去脉。 使用说明: 要下载模型,请访问网站并从库中选择所需的模型。该网站还提供了一系列使用该软件的教程和指南。 35. Pinshape Pinshape是一个提供一系列3D打印模型的网站。网站上提供的型号质量很高,因此您可以确保您的最终印刷产品看起来很棒。该网站提供了广泛的模型,包括从家居用品到小雕像和珠宝的所有物品。 但这还不是Pinshape所能提供的全部!该网站还允许用户上传和共享自己的3D模型。这意味着您不仅可以下载出色的模型,还可以通过分享自己的设计为社区做出贡献。此外,Pinshape 提供了一系列自定义选项,因此您可以调整和调整模型以满足您的特定需求。 使用说明: 要下载模型,请在网站上创建一个帐户,搜索所需的模型,然后单击下载按钮。该网站还为每种型号提供了一系列定制选项。 36.Yeggi Yeggi 提供了大量免费的 3D 模型,您可以下载各种格式的模型,例如 STL、OBJ 和 FBX。该网站易于使用,您可以按关键字、类别或特定网站搜索模型。 Yeggi 对于任何寻找 3D 模型的人来说都是一个很好的资源。它提供了大量的模型集合,从日常物品到复杂的机械,以及介于两者之间的一切。该网站的收藏量在不断增长,每天都有新的型号增加。 使用说明: 要下载模型,请在网站上搜索所需的模型,然后单击下载按钮。该网站还提供指向托管模型的原始网站的链接。 37. Open3DModel 来自开放3D模型的图像 Open3DModel具有各种类别的模型,包括建筑,车辆和角色。无论您需要建筑物,汽车还是人的3D模型,都可以在此网站上找到。 该网站易于浏览,您可以按类别或关键字搜索模型。每个模型都附带预览图像和详细信息,例如文件格式、大小和多边形数量。此信息可以帮助您选择适合您需求的模型。 使用说明: 要下载模型,请访问网站,从库中选择所需的模型,然后单击下载按钮。 使用最好的 3D 资产管理工具简化您的 3D 制作流程。立即试用它们,将您的 3D 项目提升到一个新的水平! 38. 3DExport 对于那些为其 3D 设计项目寻找 3D 模型、纹理和其他资源的人来说,该平台是一个很好的资源。该网站有大量模型可供选择,包括 3D 打印对象、游戏资产等。用户可以按类别、文件格式或价格范围浏览,以找到适合其项目的完美资源。此外,3DExport 还提供一系列教程和其他 3D 资源,以帮助用户提高技能并创建更令人印象深刻的设计。 使用说明: 要使用 3DExport,只需创建一个帐户并浏览可用型号。您可以按类别、格式和价格进行搜索,以找到所需的型号。找到喜欢的模型后,只需下载它并开始在您的项目中使用它。 39.Blend Swap Blend Swap是一个社区驱动的市场,提供与Blender软件兼容的各种免费3D模型。该平台允许用户共享和下载模型、纹理和其他资产,以便在他们的项目中使用。 使用说明: 创建免费帐户后,您可以浏览社区上传的大量3D模型。当您找到要使用的一个时,只需下载它并将其导入您选择的 3D 软件即可。 40. 3DShook 3DShook 是一个高级 3D 模型市场,提供一系列用于建筑、游戏等各个行业的高质量模型。该平台提供基于订阅的模型,具有不同的定价计划,允许用户访问一系列模型。 使用说明: 注册免费帐户后,只需浏览3D模型库,选择您喜欢的模型,然后以您需要的格式下载它们。 41. Smithsonian X 3D 史密森尼 X 3D 对于正在寻找历史文物和文物的高质量 3D 模型的设计师来说,这是一个独特的资源。该平台提供了大量3D模型,这些模型是根据史密森尼博物馆和研究中心中的真实物体扫描创建的。 使用说明:
-
你了解WPS Office和Microsoft Office的这8大区别吗?两者的差异是什么?
-
JavaScript和TypeScript:你需要了解的关键差异
-
玩转短视频:透析快手和抖音的运营定位三大关键,教你一眼挑中最适合的创作舞台" 在这篇文章中,我们将深度解析快手和抖音这两个颇具代表性的短视频平台,通过对它们共性和差异的剖析,揭示短视频运营定位的三个核心维度。通过对比快手强调的“去中心化+以人为本”,以及其提倡展示多元生活的理念,你可以了解到该平台如何让每个普通人构建个人社交圈;再来看看抖音的“中心化+以内容为王”策略,它侧重于热点内容的挖掘与推广,鼓励用户围绕官方话题创作,追求爆款视频效应。 综合快手和抖音的特点,你会发现前者注重个体价值与社区黏性,适合各类人群展现自我并建立联系;而后者则聚焦内容价值与流行趋势,吸引更多人参与互动与分享。借助这些维度,你将更好地理解和挑选最适合自己创作路径的短视频平台。