x
x
54.156.76.*

最新文章 Latest Blogs

2018-01-08 YHSPY 共  654 个不明生物围观

今天听了银奎老师分享的最近火热技术圈的 Meltdown 漏洞的基本原理,才知道原来底层系统的世界是如此的丰富多彩。Meltdown 漏洞的 POC 实现基于了一种名为 “Flush & Reload” 的黑客攻击技术,这项技术的基本原理是利用 Memory 和 Cache 之间的关系,同时利用统计学的置信程度来筛选关键信息的。

2018-01-04 YHSPY 共  538 个不明生物围观

最近花了一些时间来读《重新定义团队:谷歌如何工作》这本书,在这里记录一下书中提出的关键点。怎样才能发挥团队的最大效能,同时让团队中的成员保持高涨的激情,这些都是在团队管理中会经常遇到的问题。

2017-12-24 YHSPY 共  460 个不明生物围观

最近在读《重新定义团队:谷歌如何工作》,学习谷歌在技术团队管理上的一些思考和方式。同时上周也刚刚从杭州 D2 前端技术论坛回来。在会上,来在360和阿里的技术主管也分享了各自在团队管理上的多年经验,特此整理一下会上和自己对技术团队管理的一些思考。

2017-12-17 YHSPY 共  434 个不明生物围观

一般来说,一项新技术是否会随着时代的推进而被快速地迭代和发展,要看这项技术所应用在的实际业务场景中是否有相应的技术需求,毕竟没有任何技术是会被凭空创造出来的。技术决定了业务需求的多样性,而业务需求的多样性又推动着技术不断向前发展,两者相辅相成最终才能推动行业整体的发展和进步。

2017-11-12 YHSPY 共  383 个不明生物围观

如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建如下的 SaaS 应用提供了方法论。这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。

2017-11-09 YHSPY 共  420 个不明生物围观

本篇将讨论 Docker 用于构建微服务的相关实践。如何将 Docker 用于生产环境,并且构建一个更复杂的多容器应用?同时利于链接和卷等 Docker 特性来管理 Docker 中的应用,以及 Docker 集群的管理等。

2017-11-07 YHSPY 共  408 个不明生物围观

接着上一篇文章,我们继续深入了解并学习关于 Docker 的基础知识以及相关基于 Docker 实现的典型架构解决方案。Docker 在协调线下/上多环境开发等场景下有其独特的优势。

2017-11-04 YHSPY 共  521 个不明生物围观

Docker 改变了人们日常从开发到部署的工作流方式。不仅如此,Dokcer 在云计算、大数据处理甚至深度学习基础系统架构等方面都有其用武之地和独到之处。Docker 开发的一个目的就是为了加强开发环境与部署环境的一致性。

2017-09-30 YHSPY 共  621 个不明生物围观

随着云计算、深度学习和区块链技术的发展和普及,人们对“运算力”的需求变得越来越迫切。大型公司可以通过横向扩展机房的形式来增加自己的“运算力”,但这种从物理上扩展机器的方式对一些初创的小公司来说是一笔不小得开销负担。

2017-09-07 YHSPY 共  596 个不明生物围观

由于 V8 的 "full-codegen" 编译器在解析 AST 之后生成的机器码十分冗长,因此会大量占用 V8 的堆内存。V8 为了减少生成的机器码以缓解内存的压力,尝试了大量“延迟解析和编译(Lazy parsing and compiling)”的工作。比如对于一段代码,这段代码中的函数如果没有在初始化时被调用,则该调用过程会被“延迟”,直到第一次调用时再编译该函数的代码。

    文章日期索引 Date Index

    文章类别索引 Type Index

    文章主体 Detail

    前端关键技术点杂烩

    这里总结一下 WEB 前端面试的常见问题,同时这些问题也是对一些基础的技术概念和思想的理解。对这些基本知识的掌握程度和深度决定了你的技术层级。高级工程师是必须掌握本文列出的这些知识的,资深工程师则要对这些基本概念的纵向深度进行挖掘,问题解答全部原创,转载请注明来源

    综合技术方面:

    1、网站和页面性能优化

    缓存:ETag Expire Last-Modified 三者合用,Expire 可以让浏览器完全不发起 Http 请求,若 F5 发起请求,也可以通过判断 ETag(对应浏览器字段 If-None-Match) 和 Last-Modified (对应浏览器字段 If-Modified-Since)字段是否需要更新资源还是使用 304(Not Modified) 的本地资源;

    静态资源:代码压缩合并、CSS雪碧图、分析 FTTB 是否采用 CDN、服务器开启 GZIP 压缩、图片压缩、静态资源使用独立域名,防止域名污染(静态资源不需要携带 Cookie,又叫 Cookie 隔离);

    页面结构:样式表放顶部,JS 脚本放底部,不让 JS 脚本阻碍 DOM 的加载;

    代码优化:缩短原型链,减少属性和方法的查找时间;使用事件代理代替事件绑定;减少对 DOM 的直接操作,减少页面重绘,使用 H5 新方法 requestAnimationFrame 来进行 DOM 动画,使用 createElement 代替 innerHTML 进行 DOM 插入,因为它的速度更快;

    其他方法:BigPipe 优化、BigRender 优化、Quickling 优化;

    2、字体大小常用单位

    绝对值:像素px 点pt = (DPI / 72) px;

    相对值:一个字的大小em(默认值 1em = 16px,16px 也为浏览器的默认字体大小,继承父元素的大小,为了计算通常设 html { font-size: 63%; },即 1em = 10px) 相对于根节点的一个字大小rem;

    3、CSS Reset

    CSS Reset就是由于各种浏览器解释 CSS 样式的初始值有所不同,导致设计师在没有定义某个 CSS 属性时,不同的浏览器会按照自己的默认值来为没有定义的样式赋值,所以我们要先定义好一些 CSS 样式,来让所有浏览器都按照同样的规则解释 CSS,这样就能避免发生这种问题。本质就是清除浏览器默认样式,并且进行全局样式定义,Reset 文件要在项目初期定好,这样才不会产生后期的回归测试问题。

    
    * {
        vertical-align: baseline;
        font-weight: inherit;
        font-family: inherit;
        font-style: inherit;
        font-size: 100%;
        outline: 0;
        padding: 0;
        margin: 0;
        border: 0;
    }
    

    4、弹性布局、响应式、重构

    弹性布局:Flexbox 布局模式,适用于多行多列自适应布局。

    响应式布局:媒体查询(Media Queries)和 Viewport(初始比例,最大比例,最大宽度,缩放控制)控制。

    5、什么叫优雅降级和渐进增强

    渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

    优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

    区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。

    6、HTML5 主要增强了什么

    增加了很多利于网站 SEO 的语义化标签如 header、footer、article、nav,功能性标签 canvas、video、audio 使得浏览器可以进一步摆脱插件,websocket、localstorage、websql 等新功能特性,还有很多功能化的标签属性如 autocomplete、autofocus,和很常用的 datalist 标签。

    7、Node.js 主要解决了什么问题

    虽然单进程、单线程,但其事件环机制、非阻塞IO,可以高效的处理高并发请求,并且与前端脚本语言统一。

    8、提高 CSS 性能

    加载性能:压缩样式表,不要使用 @import(诞生于 CSS2),@import 使用在低网速下会存在页面闪烁问题(link 是在加载页面前把 css 加载完毕,而 @import 则是读取到引用的文件之后再加载,会延长页面的留白期);

    选择器性能:可忽略不计。

    渲染性能:用 createDocumentFragment 对象在内存里操作 DOM、使用 class 替换来代替直接更改样式、开启GPU硬件加速;

    Repaint(重绘):当在页面上修改了一些不需要改变定位的样式的时候(比如background-color,border-color,visibility),浏览器只会将新的样式重新绘制给元素(这就叫一次“重绘”或者“重新定义样式”)。这时只需要屏幕的一部分要重画。

    Reflow(回流重排):当页面上的改变影响了文档内容、结构或者元素定位时,就会发生重排(或称“重新布局”)。

    其他:去除空规则:{};属性值为0时,不加单位;属性值为浮动小数0.**,可以省略小数点之前的0;标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后;

    9、CSS 预处理

    CSS 预处理器用一种专门的编程语言,在编写 CSS 的过程中可以使用变量、循环、递归等特性,然后再编译成正常的 CSS 文件,可以提高 CSS 编写效率,常用的预编译语言有 LESS SESS 等。

    10、关于浮动的原理和工作方式

    浮动本质就是个带有方位的 display:inline-block 属性;会打破同一行的 inline-box 模型;

    11、浮动会产生什么影响呢,要怎么处理?

    会产生高度塌陷,子元素均设置了浮动样式,父元素会失去高度。

    解决方案:父级 div 定义 overflow:hidden、结尾处加空 div 标签 clear:both、父级 div 定义伪类 :after(最后一个子元素的后边)和 zoom。

    
    .clearfix{zoom:1;}
    .clearfix:after{display:block; content:'.'; clear:both; line-height:0; visibility:hidden;}
    

    12、你了解哪些常用 CSS 选择器?以及这些选择器的使用场景?

    ID 选择器、类选择器、伪类选择器、全局选择器 ...(请跳至W3SCHOOL)

    13、你知道这些选择器的权重怎么计算?

    权值为1000:代表内联样式,如: style=""。

    权值为100:代表ID选择器,如:#content。

    权值为10:代表类,伪类和属性选择器,如.content。

    权值为1:代表类型选择器和伪元素选择器,如div p。

    *通用选择器(*),子选择器(>)和相邻同胞选择器(+)的权值都为0。

    14、你了解哪些布局?你平时有使用过什么布局实现?

    弹性布局(与流体布局相似,大小单位使用 em)、固定布局、混合布局、绝对定位布局、流体布局(宽高以百分比计算,配合媒体查询完成) ...

    12、你常用的 JS 框架有哪些?

    jQuery、Knockoutjs、VueJs、AngularJs、EmberJs、ReactJs ...(很多 MVVM 框架可以使用)

    13、你从jQuery学到了什么?

    看了源码中一些“类型检测”函数的实现,jQuery 中的这些方法完成度非常高,实现很全面,性能也是很高的。

    
    class2type = {};
    
    jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
    
        class2type["[object " + name + "]"] = name.toLowerCase();
    
    }
    
    type: function(obj) {
        return obj == null ? String(obj) : class2type[Object.prototype.toString.call(obj)] || "object";
    }
    
    isFunction: function(obj) {
        return jQuery.type(obj) === "function";
    }
    
    isArray: Array.isArray || function() {
        return jQuery.type(obj) === "array";
    }
    

    (其他知识点还有很多,异步队列,数据缓存,事件系统,异步请求等)

    14、JS 有哪些数据类型?

    null、undefined、数字、字符串、数组、对象、布尔。

    15、JS 的数据类型中哪些是引用类型?

    数组、对象。

    16、原型链

    (内容太多,请自行 Google)

    17、函数表达式和函数声明的区别

    函数表达式只有函数定义的提升,函数声明则可以将函数定义和声明同时提升;函数表达式可以放在任何地方,函数声明则只能放到全局环境中;

    18、什么是闭包,为什么要使用闭包?

    可以简单理解为“函数里的函数”,两个常见作用:一可以读取函数内部的变量、二让这些变量的值始终保持在内存中。父函数定义的变量在子函数的作用域链中,子函数没有被销毁,其作用域链中所有变量和函数就会被维护,不会被销毁。

    
    // 此处在绑定函数时的 i 是没有问题的,从 0 到 elements.length - 1;只是在子函数中的 i 是一直保持对父环境对象中的 i 的引用的,所以在调用时一直会输出 elements.length;
    for(var i = 0; i < elements.length; i++) {
        elements[i].onclick = function() {
            alert(i);
        }
    }
    // 用 IIFE 隔离外部环境对象,使父环境对象可以及时释放;IIFE 中定义的任何变量和函数,都会在执行结束时被销毁;
    for(var i = 0; i < elements.length; i++) {
        (function(n){
            elements[n].onclick = function() {
                alert(n);
            }
        })(i);
    }
    
    

    19、DOM 中 Property 和 Attribute 的区别

    Attribute 就是 DOM 节点自带的属性,例如 div 中常用的 id、class 等;Property 是这个 DOM 元素作为对象,其附加的内容,例如 childNodes、firstChild 等;

    自定义的 Attribute 不会附加到 Property 上,对于属性 Property 的赋值在IE中可能会引起循环引用,内存泄漏。

    操作 Attribute 时使用 setAttribute() 和 getAttribute() 来操作,由于 getAttribute() 可能会有浏览器兼容性问题,所以在 jQuery 中,会对该方法进行测试:

    
    div1.className = 'a';
    var judge = div1.getAttribute("className") === 'a';
    

    对于 style 和 onclick,它们的 Property 和 Attribute 分别是对象和字符串,与其他有所区别。

    20、JS 作用域链

    在一些类 C 的语言中有“块级作用域”,即花括号的每一段代码都有自己的独立作用域,而 JS 只有函数级作用域;JS 作用域链的第一个对象始终是当前执行代码所在环境的变量对象(VO),声明函数在全局作用域,此时作用域链只有一个环境对象;运行函数时作用域链顶端加入了函数内的环境对象,运行完毕时顶端环境对象被销毁,以此类推。

    JS 在查找变量时会从链的顶端(就近原则)一直向下查找。如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。全局变量总是存在于运行期上下文作用域链的最末端,因此在标识符解析的时候,查找全局变量是最慢的。

    (最好和闭包一起理解)

    21、你对前端有什么理解?

    前端工程化、组件化 ...

    22、你觉得前端体系应该是怎样的?

    开发工具、代码质量、前端框架、前端开发标准、部署流程、代码组织、代码安全、移动 Web 开发、前沿技术社区、计算机网络体系、软件工程、可视化、浏览器、编程语言。

    23、Hybrid App 

    Hybrid App 底层依赖于 Native 提供的容器(UIWebview),上层使用传统前端技术做业务开发,底层透明化、上层多样化,这种场景非常有利于前端介入,非常适合业务快速迭代。(详情需深入研究,笔者这方面研究不多)

    24、IFC、BFC、GFC、FFC

    IFC:内联格式化上下文(display:block),容器里面的子元素不会影响到外面的元素,表示盒子从左到右的水平排列方式;

    BFC:块级格式化上下文(display:inline),表示盒子从上到下的垂直排列方式;

    GFC:网格布局格式化上下文(display:grid);

    FFC:自适应格式化上下文(display:flex);

    Box: CSS布局的基本单位

    Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。

    Formatting Context

    Formatting Context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting Context 有 Block Fomatting Context (简称BFC)和 Inline Formatting Context (简称 IFC)。

    BFC布局规则

    内部的 Box 会在垂直方向,一个接一个地放置。

    Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。

    每个元素的 margin box 的左边, 与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

    BFC的区域不会与 float box 重叠。

    BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

    计算 BFC 的高度时,浮动元素也参与计算。

    哪些元素会生成 BFC

    根元素、float 属性不为 none、position 为 absolute 或 fixed、display 为 inline-block, table-cell, table-caption, flex, inline-flex、overflow 不为 visible。

    25、JS 垃圾回收机制

    标记清除:跟踪环境对象,即跟踪作用域链,GC 会把那些没有作用域影响的内存清除掉;

    引用计数:即跟踪记录每个值被引用的次数,但可能会有“循环引用”的问题;

    26、Ajax 流程

    
    // 获取 XHR 对象
    // 设置回调函数
    xmlhttp.onreadystatechange = callback;
    // 打开一个 XHR 链接
    xmlhttp.open("GET", url, true);
    // POST 请求要设置编码类型
    // xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');  
    // 发送请求
    xmlhttp.send(null);
    
    function callback() {
        if (xmlhttp.readyState == 4) {
            if (xmlhttp.status == 200) {
                console.log(xmlhttp.responseText);
            }
        }
    }
    
    

    27、Gulp 和 Grunt 的异同点?

    Gulp 基于“流”的概念,只有一次 IO 过程,类似于 Linux 里的管道,又像 jQuery 的链式调用;Gulp 更易用;

    28、浏览器可以并行下载多少个资源?

    在 HTTP/1.1 协议下一般是6个,最多不超过8个;

    29、你觉得哪些网站前端技术比较好,这些网站的架构怎样?

    举例:淘宝网,用来很多 H5 的语义化标签;降级兼容做的很好,对禁用脚本的浏览器提供友好的选项;云客服使用 WS 代替 Ajax 轮询等;

    30、淘宝网上的商品项,如图片,滚动到了才加载,是怎么实现的?

    应该是 PipeRender 技术的一种,BigRender 的原理是通过某种方式,将首屏不需要的 HTML 代码先存放起来。渲染好首屏后,再将存储好的 HTML 代码逐步渲染出来。

    31、你了解后端技术么,前后端一般是怎么配合的?

    笔者公司用的是 CakePHP 和 Laravel 两套 PHP 框架,Laravel 本身有自己的模板引擎,同时可以与 Gulp 进行无缝衔接;模板会预留出需要替换的变量位置,前后端分离处理;前端模板可以进行模板的继承与嵌套;

    32、安卓上如何实现 1px 像素线?

    因为 Retine 屏的分辨率始终是普通屏幕的2倍,导致原本 1px 的细线在手机上显示为 2px;

    IOS8 及以上可以直接使用 border-width: 0.5px; 来设置 1px 的线段,其他平台可以用 transform 将细线高度缩小一半:

    
    .hairlines li:after {     
        content: '';     
        position: absolute;     
        left: 0;     
        background: #000;     
        width: 100%;     
        height: 1px;     
        -webkit-transform: scaleY(0.5);             
        transform: scaleY(0.5);     
        -webkit-transform-origin: 0 0;             
        transform-origin: 0 0; 
    }
    
    
    

    33、流应用是什么?

    流应用,结合了原生 App 和 Web App 的优势,又消除了各自的缺点。流应用建立在 H5+ 这一突破性技术之上,通过强化 HTML5 使其达到原生 App 的功能和体验,并辅以类似流媒体的边用边下发行技术,这2项技术是流应用诞生的关键。

    34、移动设备浏览器的 click 事件 300毫秒延迟

    来源于最初的 iOS Safari 浏览器在用户点击屏幕时会等待 300 毫秒,以判断用户是想进行单击还是进行双击缩放。其他浏览器也借鉴 Safari 的特性,导致了这一问题。

    基本解决:禁用缩放(<meta name="viewport" content="width=device-width, user-scalable=no">)、设置(touch-action: none)

    完美结局:FastClick 的实现原理是在检测到 touchend 事件的时候,会通过 DOM 自定义事件立即出发模拟一个 click 事件,并把浏览器在300ms之后的 click 事件阻止掉。

    34、touchstart 的点击穿透问题

    因为在移动端浏览器,事件执行的顺序是 touchstart > touchend > click,而 click 事件有300ms的延迟,当 touchstart 事件把B元素隐藏之后,隔了300ms,浏览器触发了 click 事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。

    发布时间 : 2016-12-09 18:23:15 作者 : YHSPY 类别 : WEB前端 Miscellaneous
    查看评论
    点击已评论用户的用户名可以@他

    一语浏览 Detail

    其他 Others

    JWT(JSON WEB TOKEN)

    可用作分布式系统的单点登录验证系统(SSO)。由于 Token 中的 Signature 部分是由前两个字段和一个密钥一起进行加密后得出来的,因此前端无法擅自修改 Token 中的信息,得以保证信息的获取不会被滥用。同时由于 JWT 的 “self-contained“ 特性,原始 Session 中的信息被全部放到了 Token 中,后端不需要存储任何信息,保证了服务的无状态化,提高了可扩展性。

    数据结构:

    交互模式:

    前端 Javascript

    this 实例:

    1、非 ES5 严格模式下,函数调用的默认 this 指向 window,严格模式下指向 undefined

    2、对象中函数的 this 指向调用方;

    
    var person = {  
      name: "Jason",
      say: function(thing) {
        console.log(this.name + " says hello " + thing);
      }
    }
    person.say("world"); // "Jason says hello world"
    
    var iSay = person.say;
    iSay("world"); // "undefined says hello world"
    

    3、使用 bind 来固化 this

    
    var boundSay = person.say.bind(person);  
    boundSay("world") // "Jason says hello world"
    
    前端工程化

    GitFlow 工作流:

    1、主分支只用于 Hotfix 和发布后的发布分支合并;

    2、专门的 Develop 分支用于 Feature 分支的合并;

    3、从 Develop 分支拷贝的发布分支,发布分支只有 Hotfix 合并,发布后合并回主分支和 Develop 分支;

    4、Hotfix 分支合并回主分支和 Develop 分支;

    5、每一次到主分支的合并都需要打 Tag 以便追踪记录;

    前端 HTTP

    HTTPS 通信流程:

    前端 HTTP

    浏览器常用缓存策略流程:

    计算机原理 CP

    HTTP1.1存在的问题:

    1、TCP连接数有限(最多6-8个),导致分片(Sharding)技术滥用,一个网站的所有资源被分布在多个主机上;

    2、线头阻塞(Head of Line Blocking)问题,服务器处理请求需要按顺序进行,即发送请求时可以多个请求放到一个 TCP 连接中(Pipelining),但接收需要按顺序一个一个来处理;

    3、可选细节过多,标准过于庞大;

    4、重复的头部内容;

    HTTP2的优势:

    1、多路复用的流,可以通过单一的 HTTP2 请求来发起多重的请求-响应消息,即请求发送和接受均并行,且不需要多个 TCP 连接;

    2、使用 HPACK 算法来压缩首部内容;

    3、服务端推送:浏览器发送一个请求,返回多个相关资源的响应;

    4、二进制分帧层:位于传输层和应用层之间,首部信息被封装到 HEADER 帧中,请求体被封装到 DATA 帧中。通过单连接多复用来解决 TCP 连接到慢启动问题;

    SPDY 与 HTTP2 的区别:

    大部分特性与 HTTP2 保持一致,包括服务器端推送,多路复用和帧作为传输的最小单位。但 SPDY 的头部压缩使用的是 DEFLATE 算法,而 HTTP2 使用的是 HPACK 算法,压缩率更高。

    另一种协议 QUIC(Quick UDP Internet Connections):“HTTP2 on UDP”

    1、使用 QPACK 代替 HPACK;

    计算机原理 CP

    内存对齐主要遵循下面三个原则:

    结构体变量的起始地址能够被其最宽的成员大小整除;

    结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节;

    结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节;

    前端 Javascript

    在某些情况下,JS 引擎的优化 Pre-Parse 过程会被浪费。比如某些在 JS 文件加载时就运行的函数在进行 Pre-Parse 之后还需要再进行一次 Full-Parse,之前的 Pre-Parse 阶段完全浪费。这种情况下可以使用 IIFE 来省去这个 Pre-Parse 阶段(V8 支持)。

    
    var constants = (function constants(){
        function sayHi(name){
            var message = "Hi " + name + "!"
            print(message)
        }
    
    sayHi("Sparkle")
    })()
     
    前端 Javascript

    日常开发如果遇到后端接口传过来大整数,比如订单号,由于 JS 最大安全数位数有限,所以可能会发现解析出的数据与和传过来的字符串数据值不相符。可以通过正则进行对应字段的替换,讲数字类型替换成字符串(注意标准 JSON 格式是双引号)

    
    replaceNumberToStringInJson(fields, json) {
      let result = json
      fields.forEach((field) => {
        result = result.replace(new RegExp(`"${field}":\\s([\\d.]+)`, 'g'), `"${field}": "$1"`)
      })
    
      return result
    }
     
    前端 Javascript

    使用npm check来检查 NPM 包的更新状态。

    
    npm check -u -g  # 检测全局依赖
    npm check -u     # 检测当前项目的依赖
    

    代码库 Code Depot

    React 实例 - 单一数据源原则
    
    const scaleNames = {
      c: 'Celsius',
      f: 'Fahrenheit'
    };
    
    function toCelsius(fahrenheit) {
      return (fahrenheit - 32) * 5 / 9;
    }
    
    function toFahrenheit(celsius) {
      return (celsius * 9 / 5) + 32;
    }
    
    function tryConvert(temperature, convert) {
      const input = parseFloat(temperature);
      if (Number.isNaN(input)) {
        return '';
      }
      const output = convert(input);
      const rounded = Math.round(output * 1000) / 1000;
      return rounded.toString();
    }
    
    function BoilingVerdict(props) {
      if (props.celsius >= 100) {
        return <p>The water would boil.</p>;
      }
      return <p>The water would not boil.</p>;
    }
    
    class TemperatureInput extends React.Component {
      constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
      }
    
      handleChange(e) {
        this.props.onTemperatureChange(e.target.value);
      }
    
      render() {
        const temperature = this.props.temperature;
        const scale = this.props.scale;
        return (
          <fieldset>
            <legend>Enter temperature in {scaleNames[scale]}:</legend>
            <input value={temperature}
                   onChange={this.handleChange} />
          </fieldset>
        );
      }
    }
    
    class Calculator extends React.Component {
      constructor(props) {
        super(props);
        this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
        this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
        this.state = {temperature: '', scale: 'c'};
      }
    
      handleCelsiusChange(temperature) {
        this.setState({scale: 'c', temperature});
      }
    
      handleFahrenheitChange(temperature) {
        this.setState({scale: 'f', temperature});
      }
    
      render() {
        const scale = this.state.scale;
        const temperature = this.state.temperature;
        const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
        const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
    
        return (
          <div>
            <TemperatureInput
              scale="c"
              temperature={celsius}
              onTemperatureChange={this.handleCelsiusChange} />
            <TemperatureInput
              scale="f"
              temperature={fahrenheit}
              onTemperatureChange={this.handleFahrenheitChange} />
            <BoilingVerdict
              celsius={parseFloat(celsius)} />
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <Calculator />,
      document.getElementById('root')
    );
    

    使用方法:浏览器。

    代码说明:完整的 Reactjs 代码片段。

    一个完整的 React 实例
    
    // sub-component
    function ListItem(props) {
      // Correct! There is no need to specify the key here:
      return <li>{props.value}</li>;
    }
    
    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        // Correct! Key should be specified inside the array.
        <ListItem key={number.toString()}
                  value={number} />
    
      );
      return (
        <ul>
          {listItems}
        </ul>
      );
    }
    
    class Clock extends React.Component {
      constructor(props) {
        // 确保 props 能够正确传入;
        super(props);
        // Bind this
        this.handler = this.handler.bind(this);
        this.state = {
          date: new Date(),
          counter: 0,
          showWarning: true
        };
      }
      // 生命周期 Hook 函数;
      componentDidMount() {
        // 不需要在 View 中显示的属性不需要放到 State 中;
        this.timerID = setInterval(
          () => this.tick(),
          1000
        );
      }
    
      componentWillUnmount() {
        clearInterval(this.timerID);
      }
    
      tick() {
        this.setState({
          date: new Date()
        });
      }
      
      handler() {
        this.setState({
          counter: this.state.counter + 1
        });
      }
    
      render() {
        const numbers = [1, 2, 3, 4, 5];
        // JSX 中的 Callback 函数需要在构造函数中绑定 this 指针;
        return (
          <div>
            <NumberList numbers={numbers} />
            <h1 onClick={this.handler}>Hello, {this.props.user.toString()}!</h1>
            <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
            <h2>Counter: {this.state.counter}</h2>
            <p>{this.state.counter > 2 && <WarningBanner warn={this.state.counter} />}

    </div> ); } } ReactDOM.render( <Clock user="YHSPY"/>, document.getElementById('root') );

    使用方法:浏览器。

    代码说明:完整的 Reactjs 代码片段。

    Node8 之 Util.promisify 常见用法
    
    var util = require('util')
    
    const wait = (delay, callback) => {
      const id = setInterval(() => {
        const rand = Math.random()
        if (rand > 0.95) {
          callback('Got data successfully!', null)
          clearInterval(id)
        } else if (rand < 0.1) {
          callback(null, 'Sorry, something wrong!') 
          clearInterval(id)
        } else {
          console.log("Waiting...")
        }
      }, Number(delay))
    }
    
    /*
      wait(1000, (data, err) => {
        if (err) {
          throw new Error(err)
        }
        console.log(data)
      })
    */
    
    // Use util.promisify
    util.promisify(wait)(1000).then(data => {
      console.log(data);
    }).catch(err => {
      console.error(err);
    })
    
    // Use async/await instead
    waitAsync = util.promisify(wait)
    let asyncFunc = async () => {
      let result;
      try {
        result = await waitAsync(1000);
      } catch (err) {
        return console.error(err);
      }
      return console.log(result);
    };
    asyncFunc().then(data => {
      // undefined
      console.log(data)
    })
    

    使用方法:Node8 命令行下直接运行。

    代码说明:Node8 新增的函数可以直接 Promise 化一个特定格式的函数,函数的回调函数需要符合 Node 的标准回调函数格式 。

    Leetcode - 169.Majority Element HashMap基础解法
    
    public static int majorityElement(int[] nums) {
        if (nums.length == 0)  // 如果数组长度为0则返回-1
        	return -1;
        
        int arrLen = nums.length;
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0;i < arrLen; i ++) {
        	int currentVal = 0;
        	if (map.containsKey(nums[i]))  // 如果HashMap中存在该值对应的元素则使用该值
        		currentVal = map.get(nums[i]);
    
        	if (currentVal > arrLen / 2) {  // 如果满足条件则返回该元素
        		return nums[i];
        	} else {
        		map.put(nums[i], currentVal + 1);  // 否则对应元素值加一
        	}
        }
        
        return -1;
    }
    

    使用方法:Eclipse新建工程,直接复制到主类里,通过类名静态调用即可。

    代码说明:本段代码为Leetcode题目“169.Majority Element”的实现代码,算法类代码建议先做题,再参考。题目详情请参考文章《Leetcode每日一题 - 169.Majority Element》。

    Leetcode - 219.Contains Duplicate II 窗口检测解法代码片段
    
    public static boolean containsDuplicateOptimizeFurther(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();  
        int start = 0, end = 0;  // 定义窗口的首尾指针
        for(int i = 0; i < nums.length; i++) {   // 开始遍历
            if(!set.contains(nums[i])) {    
                set.add(nums[i]);   
                end++;   // 如果Set中没有此元素则加入,尾指针后移
            } else { 
                return true;   // 有则返回True
            }
            
            if(end - start  > k) {  // 保持首尾指针距离不大于k  
                set.remove(nums[start]);    //如果大于则移除首指针元素
                start++;   // 移除后首指针后移
            }  
        }  
        return false;
    }
    

    使用方法:Eclipse新建工程,直接复制到主类里,通过类名静态调用即可。

    代码说明:本段代码为Leetcode题目“219.Contains Duplicate II”的实现代码,算法类代码建议先做题,再参考。题目详情请参考文章《Leetcode每日一题 - 219.Contains Duplicate II》。