avaScript和Java有什么联系
根据目前我自己的理解,不要被名字有相似字节所欺骗,这两个语言其实没有什么联系,如果说有的话,应该就是关键字和对象的一些范畴有点相似或者说是有种模仿的感觉。但是实际上一个作为脚本的轻量语言[^7],一个作为有完整体制的大型语言[^8],两者是没有任何可比性的。
JS的内链外链
内链
? JS的内链,也就是在html文件内的调用使用与css类似,也有两种方式,即在html文件的<head></head>中书写使用或是在<body></body>中使用。
<head></head>内书写
? 在<head></head>中对JS的代码进行书写时,我们使用<script></script>对我们的JS代码进行包裹,与html及CSS的法则一样,其作用也是用来标明其JS的代码块属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script>
function displayDate(){
document.getElementById("demo").innerHTML=Date();
}
</script>
</head>
<body>
<h1>我的第一个 JavaScript 程序</h1>
<p id="demo">这是一个段落</p>
<button type="button" onclick="displayDate()">显示日期</button>
</body>
</html>
###### <body></body>内书写
? 与在<head></head>中类似的,我们在<body></body>中对JS的书写和使用同样是在<script></script>中实现,其作用也与上述的一致。
<!DOCTYPE html>
<html>
<body>
<script>
document.write("<h1>This is a heading</h1>");
document.write("<p>This is a paragraph.</p>");
</script>
</body>
</html>
外链
与css有些不同的,JS的外链同样使用的是<script></script>标签来实现。JS即可以出现本地的JS文件的链接,也可以调用网上的JS文件进行链接,但调用网络上的文件有可能会受到目标文件服务器和网络的影响,使用的频率没有本地的调用高。
? 调用本地JS文件:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../js/js_for_Seat_selection_nterface.js" ></script>
</head>
<body>
</body>
</html>
调用网络的JS文件:
<!DOCTYPE html>
<html>
<head>
<script src="http://www.lanrenzhijia.com/ajaxjs/jquery.min.js"> </script>
</head>
<body>
</body>
</html>
? JS的外链与css类似的,也可以在同个文件里调用多个JS文件使用。其中还有很多较css的相似部分就不在这里重复说了,可以参考之前的css部分内容。
JS的语法关键字
JS的语法关键字有很多很多,因为JS是一门以对象为基础的语言,我们在使用会发现很多例如document.getElementById("demo").innerHTML=x;的语句,这里的getElementById(),innerHTML其实都是JS为我们已经封装(可以理解为打包)好了的方法和方法中的参数。所以我们在这里主要介绍一些基本的关键字。
function
function的作用其实很简单,就是声明一个函数,表明我这里的是一个函数,我们用一个看例子来看:
function myFunction(){
var x="";
var time=new Date().getHours();
if (time<20){
x="Good day";
}
document.getElementById("demo").innerHTML=x;
}
上述的例子就是为我们声明了一个叫做myFunction的的函数,其后的花括号中包含的就是函数中的内容。
var
在JS中,var的作用就是声明一个变量,在JS中,对于变量的类型没有严格的规定,所以JS也是一门弱语言,被定义的变量只有在第一次被赋值时才会被系统分配相应数据类型的空间。
var a;
a=10;
但实际上我们会发现,在实际使用时不仅仅是var可以声明一个变量,$也可以成功声明一个变量,甚至不需要任何的申明关键字也可以直接创建一个变量。但实际上是有非常大的差别的,$是JQ中的一个已经过定义的自定义函数名,而在单纯的JS中是没有任何意义的,一般是在你的文件已经引入了一个JQ数据库后才出现$也可以创建变量的情况,而相较于不使用任何关键字而直接创建一个变量,其实质是在整个JS文件的最上层windows中创建了一个对象属性,详细的解释我会在文末提供一个网络来源的博客地址,其中对创建对象属性有一个较为详细的解释。
所以我们在声明创建变量时一定要使用var关键字,不使用任何关键字创建变量,虽然可行,但却存在着语法错误。
new
与其它的面向对象方法一样的,JS中创建对象所使用的个关键字也是new,我们通过它来创建一个对象。
person=new Object();
在上述的例子中,我们创建了一个名为person的对象,object我们在这里可以简单的理解为一个类型为对象的数据结构。这句代码的意思就是创建一个对象,对象名为person。
JS的结构语句
其实说是JS的结构语句,我们不难发现的,这些结构语句其实很多都是我们在其他语言中也能见到的语言语法,我们在这里也是将它们简单的归类再来说明一下。
###### if else
if else语句主要的作用其实也很简单,就是做一个判断,就像它的翻译 一样——如果….就….. 否则…..。
if(...){
...
}
else{
....
}
? 上述的就是它的基本格式,我们可以看到在if后面的小括号中会有一个判断语句,其中的语句用来判断真假来控制语句的执行部分。花括号中的就是满足条件时执行的语句。
这一条语句是可以嵌套的,我们通过对它的嵌套来进行多层的判断。
if(...){
if(...){
...
}
else{
....
}
}
else{
....
}
while
我们先来看它的格式:
while(...){
...
}
while是一个循环语句,在关键字后面的小括号中,也同样是一条判断语句,用来控制循环的执行。在花括号中是我们的循环内容。
do while
可能我们会发现,这条语句和上一条语句非常的相似,我们还是先来看它的格式:
do{
...
}while(...)
它一样是一条控制循环的语句,不过和上一个语句有所区别的,它是先循环后判断,而while是先判断后循环,有的时候我们在不以言大哥情况下使用会达到不一样的效果。
for
js for( var i=0;1<=10;i++){ ... }
for语句也同样是一个循环语句,我们在上面举出了一个实例,从例子中我们看到,for和它的循环语句是有区别的,我们需要在判断的语句中定义变量,规定执行循环的条件,及控制循环的条件变化。
但实际上,有些时候我们只需要写明控制循环的条件语句就可以了,其他的两条语句可以不在括号中写出。但要注意的,我们需要保留它的分号,不然会出现语法错误。
switch
js switch(...){ case '...': ...;break; case '...': ...;break; .... default:...; }
这是一个条件选择语句,我们通过判断语句来选择到一个具体的分支,执行相应的语句。
有关于break,default 的作用,我们就不细说了,大家可以去网上查看它的详细信息。
JS的效果实现(HTML的事件响应)
我们已经很简单的介绍了一下JS的语法和关键字,那么我们下面来说在网页中如何触发JS的代码,又或者说是如触发相应的事件。
##### 点击事件
点击事件就是通过页面点击触发的事件,我们要注意的,在网页中其实不是只有按钮才可以作为点击事件的载体,基本上所有的网页元素都可以作为点击事件的载体。也就是说其实我们可以在任意一个元素中添加一个点击事件。
? 下面我们来看常用的格式:
<html>
<body>
<input type="checkbox" name="ticket_seat"id="tucket_18" class="ticket_input"value="18"onclick="ticket_onclick()">
<script>
function ticket_onclick(){
...
}
</script>
</body>
</html>
? 在上述的例子中我们可以看到,在标签中加入一个onclick属性,在后面写上要触发的函数名。这样我们在点击网页上的元素之后,我们就可以触发相应的JS函数。
对于我们的onclick字段,我们可以像常规的函数调用来看待它,也就是说,我们也是可以通过它向函数传入参数。
后记:对于大部分转行的人来说,找机会把自己的基础知识补齐,边工作边补基础知识,真心很重要。
"我们相信人人都可以成为一个IT大神,现在开始,选择一条阳光大道,助你入门,学习的路上不再迷茫。这里是北京尚学堂,初学者转行到IT行业的聚集地。"
者 | Adrien Joly
译者 | 张卫滨
策划 | 丁晓昀
有时候,JavaScript(甚至带有类型检查的 TypeScript)会因为其不可预测的特性和缺乏约定而遭到批评。对于那些知道 JavaScript 是为 web 浏览器设计的脚本语言的人来说,这就不足为奇了。
但是,现在它已经成为开发全栈 web 的首选语言,也是跨平台移动应用的热门方案。那么,当开发人员的 JavaScript/TypeScript 代码库开始老化,由此带来的复杂性痛苦地增长时,他们该采取什么行动才能最大限度地减少资源浪费并保持工作满意度呢?
本文将基于我 10 多年来编写 JavaScript 代码的经验和 5 年多拯救 JS/TS 项目的经历,向读者介绍如下内容:
在开发下一个特性时,每个警告、类型错误或非正常的测试都会让开发人员浪费时间、精力和专注度。
代码警告尤其令人讨厌,因为开发人员会习惯性地忽略它们,“只要一切按预期运行就好”。因此,它们会迅速累积,当我们遇到缺陷、事故或系统的意外行为时,就很难将其作为有用的线索。
类型错误就是一个很好的样例。当我们的用户遵循“快乐路径(happy path)”时,这些错误似乎无关紧要,因为软件似乎能够按照预期运行。所以,我们可能会使用@ts-ignore、any或类型断言来暂时忽略它们。但是,这样做的话,就意味着如果有一天用户选择不同的路径,就会面临运行时错误。
这样的话,开发人员就需要调查、重现和修复一个新的缺陷,而这个缺陷恰恰是他们几个月前允许走捷径所造成的。如果你的代码被各种警告和/或暂时忽略这些警告削弱了质量,那么找到这个捷径将耗费大量的时间。
当生产环境的数据库因“内存不足”错误而崩溃时,该警告可能会帮助开发人员找到崩溃的原因
警告和类型错误是查找缺陷和事故的线索。我们累积(或忽略)的警告和错误越多,开发人员就会花费越多的时间去调查。如果代码是他们很久以前编写的,那情况就会更糟糕了。
类型检查器认为缺少一个预期的属性。忽略这个错误将意味着要承担持久化不一致数据的风险,在几个月之后,你可能需要花费几天的时间来调查和解决这个问题
有许多静态代码分析工具可供使用,最常用的包括:
警告也可能来自其他工具:依赖安装器(如npm和yarn)、打包器(如webpack)、代码处理器(babel、scss)和执行环境(CI 运行器)。不要忽视它们!
如果遵循这些建议会让你的代码变得非常冗长和/或复杂(比如防御式代码),你可以需要对其进行重新设计。
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint:errors": "eslint . --quiet",
"lint:typescript": "tsc --noEmit --skipLibCheck",
"lint:jsdoc-typing": "tsc --noEmit --allowJs `find ./ -name '*.js' -name '*.d.ts'`"
},
复制代码
借助静态代码分析器和 npm 脚本,能够让开发人员轻松快速地探测有问题的代码
安装和配置静态代码分析工具是一个良好的开端,但这还不够。
要想取得持续的成功,要确保开发团队做到如下几点:
如下几种策略可能会提供帮助:
当某项职责没有人负责时,集体责任往往会被其他“优先事项”所取代(比如,本周多交付一个特性,但是代价是忽略一个警告)。
定期轮换角色,确保每个人都能参与其中并保持积极性。
现在,我们有了一支致力于保持代码库整洁的团队,我们相信用户很少会遇到编程错误。
但是,业务逻辑中的错误该怎么办呢?
例如,如果一个新添加的功能破坏了另一个功能该怎么办?如果开发人员从一开始就误解了该功能的预期行为,又该怎么办?如果这样的错误最终导致了严重的收入损失又该如何处理?
与编程错误类似,业务逻辑问题可能会在生产环境由用户发现,但我们更希望尽早发现它们。因此,定期测试软件非常重要,这个过程可以使用自动化和/或手动测试。
从业务角度看,测试有两个作用:
确保功能性测试(也称为“验收测试”)涵盖大多数关键业务特性,单元测试或集成测试涵盖大多数关键技术组件。此外,确保持续集成在任何测试失败时都能向开发人员提供可执行的反馈。
对于有些开发人员来说,将测试工作委托给其他人(如产品负责人或 QA 团队)是很有诱惑力的做法。在每个新特性完成后,进行一次这样的委托测试,以确保特性实现符合功能性需求,并进行协作迭代,这样做可能是合理的。
但是,委托他人进行回归检测并不是一个好主意,原因包括:
回归测试是一项痛苦且可能代价高昂的负担,尤其是需要不同角色(如产品负责人和开发人员)必须协作的情况下。从长远来看,回归测试自动化意味着可以节省大量的时间,而且开发人员具有编写自动化测试的技能,所以,开发人员首先要承担起检测回归的责任,而不必让其他角色参与进来,这符合他们的利益。
从最关键的业务特性开始。要找出这些特性,你可以问自己:“就收益和/或减少成本而言,在生产环境中可能发生的最糟糕的事情是什么?”
例如,电子商务网站的回答可能是如下的特性:
基于这些业务关键的用例,从它们开始编写端到端的自动化测试肯定就是非常有意义的。
在每次代码更新或添加到代码库之时,在将其部署到生产环境之前。
借助git hook,在每次提交时运行测试可能就足够了,因为它能可靠地运行,而且其持续时间不会导致开发人员编写更少的测试。
不管是否使用git hook,都要确保每次推送可用于生产环境的代码时,测试能在某处运行(例如,最好是在持续集成环境中)。
在持续集成环境中,每次提交都会运行代码检查和自动化测试。
需要优化的变量包括:
如果你的团队在编写自动化测试和/或可测试代码方面经验不足,那么可以从一些端到端测试开始。然后,逐步增加对范围更小的代码单元的测试。这样做可以激励开发人员编写易于测试的代码。例如,通过隔离责任、减少耦合和/或将业务逻辑写成纯函数。遵循依赖注入架构是实现这一目标的好方法。(参见六边形架构或简洁架构)
自动化测试(如本文所述)的目的是探测团队的功能性范围内的回归,而不是第三方的功能。基于这一点,在测试中 Mock 第三方是合理的。
也就是说:
探测自己的代码中的问题和第三方 API 中的问题并不遵循相同的生命周期:
你需要持续监控第三方提供商是否能够正常运行并达到预期效果。但是,第三方错误不一定能够在发生之时就探测到,因此最好是定期监控,而不是在开发人员每次推送代码变更的时候进行监控。
所以,需要搭建两个专门的流水线:
为了编写长期最有用、最健壮的测试,我建议遵循F.I.R.S.T.原则。确保开发人员不会滥用mock。
假设你的代码库已经或者将要开发数年的时间,那么随着时间的推移,它很可能会在代码风格和质量方面失去内聚力。更糟糕的是,由于技术债务、缺乏测试或意外复杂性的积累,某些组成部分的维护可能会变得很复杂。
在这种情况下,要像上文所建议的那样,在整个代码库中对代码实现一致的内聚预期可能会变得很复杂。不过,这也没有关系。
你不希望看到的是期望值降低到一个最低的平均水准。这样的话,你可以把代码划分为不同的范围,并为每个范围设置不同的期望水平。
例如,考虑一个即将为电子商务网站实现新特性的团队。他们希望这个新特性能够比代码库中的其他特性更健壮、更易于维护。为了实现这一点,他们在配置静态代码分析工具(如 ESLint 和 TypeScript)时采用比代码库的其他部分更严格的规则,并针对专门为该特性而创建的目录使用覆盖的方式启用更多的规则。通过这种方式,团队可以提高新代码的质量,而不必急于对代码库中“遗留”的部分进行现代化处理。
"rules": {
"prettier/prettier": "error",
"deprecation/deprecation": "warn"
},
"overrides": [
{
// Tolerate warnings on non critical issues from legacy JavaScript files
"files": ["*.js"],
"rules": {
"prefer-const": "warn",
"no-inner-declarations": ["warn", "functions"],
"@typescript-eslint/ban-ts-comment": "warn",
"@typescript-eslint/no-var-requires": "off"
}
},
{
// Enforce stricter rules on domain / business logic
"files": ["app/domain/**/*.js", "app/domain/**/*.ts"],
"extends": ["async", "async/node", "async/typescript"],
"rules": {
"prefer-const": "error",
"no-async-promise-executor": "error",
"no-await-in-loop": "error",
"no-promise-executor-return": "error",
"max-nested-callbacks": "error",
"no-return-await": "error",
"prefer-promise-reject-errors": "error",
"node/handle-callback-err": "error",
"node/no-callback-literal": "error",
"node/no-sync": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/promise-function-async": "error"
}
}
]
复制代码
通过配置覆盖,我们可以为不同的部分设置不同的 ESLint 规则
与之类似,如果要对整个代码库进行现代化改造,也要循序渐进。你可以创建一个具有更严格规则的专用目录,并逐渐将遗留代码迁移至该目录,同时修复代码的警告和类型错误。
有种方式是逐步将功能范围中陈旧的部分迁移到更好的设计中。例如,选择一个难以编写自动化测试的特性,并将它的实现迁移到六边形架构中,将业务/领域逻辑根据输入命令(即“API”)和副作用(即“SPI”)分离开来。通过编写自动化测试来指导迁移,并将新的实现放在具有更严格静态代码分析规则的专用目录中。
import { makeFeatures }=from './domain/features';
import { userCollection } from './infrastructure/mongodb/UserCollection';
import { ImageStorage } from './infrastructure/ImageStorage.js';
/** @type {import('./domain/api/Features').Features} Features*/
const features=makeFeatures({
userRepository: userCollection,
imageRepository: new ImageStorage(),
});
routes.post('/avatar', (request, response)=> {
features
.setAvatar(request.session.userId, request.files[0])
.then(
()=> response.json({ ok: true },
(error)=> response.json({ ok: false })
);
});
复制代码
setAvatar特性经过了重新设计,由于采用了依赖反转,使其易于单独进行测试。下面是我们迁移另一项特性的过程,即播放列表删除
如果你决定遵循这一路径,如下是一些建议:
在迁移完每个限界上下文之后,你将会得到一个代码库,在代码库中 100%的代码都应按照更严格的规则进行检查。
尽管使用了静态分析工具来检测缺陷,使用了自动化测试来探测回归,但用户还是会在生产环境中发现问题。这是无法避免的。但是,有一种方法可以降低出现此类问题的概率,并缩短团队修复问题的时间:
简约版答案:因为DORA研究项目发现,大多数执行团队每天都在进行部署,或者每天部署多次。
详尽版答案:
在生产环境中出现意料之外的行为是可以的。在有些情况下,这甚至是一件好事。
当意料之外的行为给企业和/或开发团队带来巨大损失时(例如,网站中断,导致几个小时无法使用),开发人员应该采取措施防止类似的事件再次发生。
有多种方式可以探测生产环境中的问题:
无论是哪种情况,开发人员都需要以下信息:问题是什么、问题的具体表现(如错误信息)、如何重现问题(如环境+过程),以及用户的初衷和期望是什么。
但是,如何在最糟糕的情况下获得这些数据呢?这就是错误监控工具(如Sentry)的用武之地了。通过将它们注入到生产环境中运行的产品中,它们就能像探针一样检测运行时错误,并将它们汇总到已知错误的列表中,直到每个错误都被开发人员修复为止。此外,它们还会获取有关错误上下文的数据(如用户代理、所使用软件的版本、操作系统、确切的时间戳等),以帮助开发人员重现错误。
但令人遗憾的是,与静态代码分析器类似,这些工具并不能解决问题。因此,与警告和类型错误一样,要确保尽快处理每个错误。团队让错误累积得越多,使用这些工具的动力和效率就会越低。
此外,在使用这类监控工具时,请确保个人和/或机密数据不会从系统中泄露出去。
从战术上讲,有许多方法可供选择。你可以让一名开发人员负责修复生产环境的错误,并将其作为最优先的事项。这个角色可以定期轮换(比如每天),这样可以激励每个人都编写更健壮的代码。或者,也可以在每天的会议上将新错误单独分派给志愿开发人员。
不必慌张!当生产环境中发生事故时,都要遵守如下程序:
避免重蹈覆辙的关键在于上述程序的最后一步。
这也是经常被忽视的过程。大多数情况下,是因为没人觉得自己有责任这样做。很多时候,是因为产品负责人(或产品团队)向开发人员施压,要求他们优先完成开发计划中的特性,而不是保护现有代码和/或调整开发流程。有时,开发人员自己也会决定开发更多的特性,而不是避免再次犯错。
调查事故根本原因时的注意事项
在这个方面,“5 个为什么(5 WHY)”技巧是很有用的。例如:
在本例中,根本原因是整个网站都依赖于遗留的会话管理后端,这使得导航难以预测,有时还会导致生产环境崩溃。因此,除非团队修复传统的会话管理后端,否则类似的崩溃很可能很快就会在生产环境中再次发生。团队现在应该修复遗留的会话管理后端吗?也许不用。但是他们应该努力制定一个能够实现该目标的补救计划。
让一位开发人员负责确保尽快发现生产中的意外行为(如运行时错误、缺陷、事故……),尽快修复,并采取措施防止今后再次发生各类问题。
通过这种方式,开发人员能够感受到有能力在良好的条件下开展工作。例如,在生产过程中设置恰当的监控和日志,确保撰写有用的事后报告,并采取预防措施。
当信心达到良好水平时,逐步增加部署频率。
此时,开发人员就具备了编写高质量软件,并尽快发现缺陷的能力。这些缺陷最好是在设计或实现时发现,而不是在生产环境中。他们能够快速发现并修正生产环境的错误,不会重复犯同样的错误。他们对自己的代码和开发流程充满信心,因此每天都能在生产中实现改善。而且,他们在对软件功能化范围进行预期改善的同时,也会逐步改善代码库中最古老部分的设计和质量,使其保持健康、稳健并易于长期维护。
但是,令人遗憾的是,这种平衡很快就可能被瓦解。举例来说:
防止或解决这类情况可能会非常困难,因为这需要良好的领导力和/或软技能。
一个常见的错误是培养某种思维定式,即开发人员应该主要致力于实现优先的、计划好的和设计好的特性。
这样做是有问题的,因为:
下面是一些关于如何避免上述陷阱的建议:
JavaScript 语言及其不断变化的软件包和实践组成的生态系统会使代码库迅速变得难以维护。正如我们在本文所讨论的那样,无需从头重写所有的内容,也无需暂停新特性的开发,就可以避免由此造成的开发速度和/或代码质量的下降。
关于如何在 TypeScript 和 JavaScript 项目中应用这些推荐做法的更多实用建议,我建议你参考Yoni Goldberg的最佳实践列表。它们是为 Node.js(后端)项目编写的,但其中很多也适用于前端代码库。
原文链接:前端老手10年心得,JavaScript/TypeScript项目保养实用指南_架构/框架_InfoQ精选文章
TML+CSS学完好久了,一直没啥时间总结,现在总结了下学的过程:
之所以放在一起总结,是因为HTML和CSS没有啥很多的编程逻辑,都是需要去记住并且熟练使用的,熟练使用是得去一个个敲过一遍。所谓的代码量积累好像就是这么回事,只有多敲才能会。
小白用的哔哩哔哩上的教程视频,因为个人学习方法的原因,都是跟着那教程去敲的,当然课后练习的话,都是自己先摸索敲了一遍在去看的讲解,小白觉得这样可以加深印象。
还有就是没有熟练之前要天天的去练,哪怕一天半小时也好。因为一旦一天没有练就会忘掉,还得回去找之前的笔记来看。(因为有事耽搁了两三天没去学,结果又重头的看了一遍,血淋淋的学习效率教训。不管怎样,贵在坚持。)
当然,因为小白基础是真的差,没有什么教程是可以完完全全都讲完的,使用小白看完了哔哩哔哩的教程又跑去了网易云课堂找了一份HTML+CSS的教程来看,为的是查漏补缺。
有一种播放叫做1.5倍播放。看的过程,别跟播放器里一倍的速度看,调成1.5倍或是2.0倍播放速度,因为那些东西,多数都是理解使用的。哪怕忘了,百度一下就可以直接搞定了。打基础阶段所以还是记住熟练使用才好。
HTML小白也就看了两天吧,用了半天做了下练习;CSS对于零基础的人来说建议12-15天,当然小白之前有过这些概念,所以用了五天多点的时间。JS才刚刚开始学,所以不知道时间怎么算才好。因为前端三大基石:HTML+CSS+JS,HTML+CSS学习所使用的时间占比才百分之五,剩下的百分之九十五都是JS的学习时间。
找课程时记住,找一两个课程,一个全心去学,一个查漏补缺就好,别一会儿这个课程看一下,那个课程看一下的。这样子反而会使自己心浮气躁没法静下心来去学。打基础的视频教程,其实都一样的,没啥有特别好的特别坏的。
*请认真填写需求信息,我们会在24小时内与您取得联系。