自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

sifanchao的博客

什么都有比什么都没有更可怕!只有肯用心、持之以恒,就走在成功的路上。

  • 博客(212)
  • 收藏
  • 关注

原创 浏览器

浏览器是如何渲染UI的浏览器获取HTML文件,然后对文件进行解析,形成DOM Tree与此同时,进行CSS解析,生成Style Rules接着将DOM Tree与Style Rules合成为 Render Tree接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标随后调用GPU进行绘制(Paint),遍历Render Tree的节点,并将元素呈现出来浏览器重绘与重排的区别重排: 部分渲染树(或者整个渲染树)需要重新分析,并且节点尺寸需要重新计算,表现为重

2020-06-02 21:15:08 338

原创 ajax

AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是一种创建交互式网页应用的网页开发技术。Ajax的工作原理相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做,只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。要完整实现一个AJAX异步调用和局部刷新,通常需要以下几个步骤:创建XMLHttp

2020-06-01 14:48:15 319

原创 前端网络安全

有哪些可能引起前端安全的的问题跨站脚本 (Cross-Site Scripting, XSS): 一种代码注入方式, 为了与 CSS 区分所以被称作 XSS. 早期常见于网络论坛, 起因是网站没有对用户的输入进行严格的限制, 使得攻击者可以将脚本上传到帖子让其他人浏览到有恶意脚本的页面, 其注入方式很简单包括但不限于 JavaScript / VBScript / CSS / Flash 等iframe的滥用: iframe中的内容是由第三方来提供的,默认情况下他们不受我们的控制,他们可以在ifram

2020-05-31 22:13:41 1827

原创 Webpack

webpack与grunt、gulp的不同Grunt、Gulp是基于任务运行的工具它们会自动执行指定的任务,就像流水线,把资源放上去然后通过不同插件进行加工,它们包含活跃的社区,丰富的插件,能方便的打造各种工作流。Webpack是基于模块化打包的工具自动化处理模块,webpack把一切当成模块,当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。webpack

2020-05-31 21:12:49 387

原创 js模块化解决方案规范

AMD是由RequireJS推动一个异步加载模块的规范,通过define定义模块,require去引用模块推崇依赖前置,在定义模块的时候就要声明其依赖的模块,提前执行CMD是由SeaJS推动的模块化规范,推崇一个模块一个文件,通过define定义模块,seajs.use来加载模块推崇就近依赖,只有在用到某个模块的时候再去require,延迟执行CommenJS是一种同步加载模块的规范,被nodejs推广开,使用module.exports和require开发UMD是AM..

2020-05-31 16:03:16 313

原创 Vue中的key到底有什么用

key是为Vue中的vnode标记的唯一id,通过这个key,我们的diff操作可以更准确、更快速。diff算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的key与旧节点进行比对,然后找出差异。diff过程可以概括为:oldCh和newCh各有两个头尾的变量StartIdx和EndIdx,它们的2个变量相互比较,一共有4种比较方式。如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦StartIdx>EndIdx表明oldC

2020-05-30 22:38:38 885

原创 虚拟DOM

为什么使用虚拟DOM因为真实dom的实现内容太多了,如果直接操作真实dom对象,对性能是巨大的浪费。虚拟dom就是一个简化后的dom对象,只存储了重要的参数。virtual dom很多时候都不是最优的操作,但它具有普适性,在效率、可维护性之间达平衡。虚拟dom类似于计算机中的缓存。包括几个步骤:用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把2所记录

2020-05-30 22:03:39 441

原创 Vue是如何实现双向绑定的

vue的双向绑定指的是数据变化更新视图,视图变化更新数据。视图变化更新数据一般就采用事件监听的方式就可以了,数据变化更新视图就需要涉及响应式原理。vue2.x的响应式原理的基础是Object.defineProperty属性。利用Object.defineProperty劫持对象的访问器,在属性值发生变化时我们可以获取变化,然后根据变化进行后续响应,在vue3.0中通过Proxy代理对象进行类似的操作。Vue三要素双向绑定其实已经是一个老掉牙的问题了,只要涉及到MVVM框架就不得不谈的知识点,但它毕

2020-05-30 17:39:46 2329

原创 computed和watch有什么区别

computedcomputed是计算属性,也就是计算值,它更多用于计算值的场景computed具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算computed适用于计算比较消耗性能的计算场景watch更多的是「观察」的作用,类似于某些数据的监听回调,用于观察props $emit或者本组件的值,当数据变化时来执行回调进行后续操作无缓存性,页面重新渲染时值不变化也会执行当需要

2020-05-30 14:53:57 1661

原创 Vue组件如何通信

如上图所示, A与B、A与C、B与D、C与E组件之间是父子关系; B与C之间是兄弟关系;A与D、A与E之间是隔代关系; D与E是堂兄关系(非直系亲属) 针对以上关系我们归类为:父子组件之间通信非父子组件之间通信(兄弟组件、隔代关系组件等)Vue组件通信的方法如下:props/$emit+v-on: 通过props将数据自上而下传递,而通过$emit和v-on来向上传递信息。prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改.

2020-05-30 14:42:39 256

原创 Vue的生命周期

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是Vue的生命周期。各个生命周期的作用生命周期描述beforeCreate组件实例被创建之初,组件的属性生效之前created组件实例已经完全创建,属性也绑定,但真实dom还没有生成,$el还不可用beforeMount在挂载开始之前被调用:相关的 render 函数首次被调用mountedel 被新创建的

2020-05-30 12:55:30 213

原创 Vue中的MVVM

MVVM 模式,顾名思义即 Model-View-ViewModel 模式。它萌芽于2005年微软推出的基于 Windows 的用户界面框架 WPF ,前端最早的 MVVM 框架 knockout 在2010年发布。Model 层:对应数据层的域模型,它主要做域模型的同步。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在层间关系里,它主要用于抽象出 ViewModel 中视图的 ModelView 层:作为视图模板存在,在 MVVM 里,整个 View 是一个动态

2020-05-30 12:43:45 263

原创 字符串转换整数 (atoi)

思路:去掉前导空格处理正负号识别数字,处理越界情况。/** * @param {string} str * @return {number} */var myAtoi = function(str) { var charArr = str.split("") var len = str.length var index = 0 // 去掉前导空格 while(index < len && charArr[index] == .

2020-05-29 01:28:49 170

原创 整数反转

class Solution {public: int reverse(int x) { long n = 0; while(x){ n = n * 10 + x % 10; x /= 10; } return (int)n == n ? (int)n : 0; }};

2020-05-28 23:32:22 152

原创 CSS基础

元素的宽度 = margin-left + border-left + padding-left + width + padding-right + border-right + margin-right

2020-05-28 22:24:17 474

原创 HTML基础

doctype的作用是什么(重要)DOCTYPE是 html5 标准网页声明,且必须声明在HTML文档的第一行。来告知浏览器的解析器用什么文档标准解析这个文档,不同的渲染模式会影响到浏览器对于 CSS 代码甚至 JavaScript 脚本的解析。文档解析类型有:BackCompat:怪异模式,浏览器使用自己的怪异模式解析渲染页面。(如果没有声明DOCTYPE,默认就是这个模式)CSS1Compat:标准模式,浏览器使用W3C的标准解析渲染页面。IE8还有一种介乎于上述两者之间的近乎标准的模式,但是

2020-05-28 21:04:13 255

原创 Z 字形变换

class Solution {public: string convert(string s, int numRows) { vector<string> temp(numRows); string res; if(s.empty() || numRows < 1) return res; if(numRows == 1) return s; for(int i = 0; i < s.siz.

2020-05-28 01:08:34 217

原创 最长回文子串

方案一:暴力依次遍历字符串,取出一组。然后将取出的子串进行反转。比较两个字符串是否相等。如果相等,则记录此时的长度。知道遍历完所有字符串的可能性。返回max最大长度即可/** * @param {string} s * @return {string} */var longestPalindrome = function(s) { if(s.length < 2){ return s } var max = s[0] for(var i =.

2020-05-27 00:47:25 115

原创 使用canvas绘制一个时钟

准备工作,设置基准设置表钟的表心位置坐标(x,y)和表钟大小(r)。创建canvas,使用getContext() 方法返回canvas对象。得到时分秒表针每走一步的度数,用来绘制扇形初始化起始位置时针因为一共12格,所以每走一步的度数为 30°分针一共60格,所以一步为 6°秒针6°为了修饰,当秒针走了10秒时,分钟多一度;同理分针走了2分钟时,时针多一度。绘制一个小刻度的扇形绘制白色表盘用白色表盘盖住上一个扇形圆,生成一个带有刻度的新扇形圆绘制大刻度绘制小白色表盘绘

2020-05-26 19:46:01 606

原创 寻找两个正序数组的中位数

方案一:暴力新建一个大小为(m+n)的数组,将两个数组的值插入到新的数组,然后进行排序,最后根据奇偶返回中位数。class Solution {public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { vector<int> nums3; nums3.insert(nums3.end(),nums1.begi.

2020-05-26 00:33:05 781

原创 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

因为字符串是由每个字符组成,而字符一共只有128个。所以我们创建一个字符数组(new Array(128)),将字符串的字符一个一个先进行ASCII转化,如果当前字符所对应字符数组的值为0,那么说明该字符没有出现,此时将此位置置为1。依次进行比较,如果字符对应字符数组的对应位置值为1,那么说明该字符为重复的,此时返回遍历值i即可。/** * @param {string} s * @return {number} */var lengthOfLongestSubstring = function(

2020-05-24 20:21:43 935

原创 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的

思路:1.判断链表是否为空,如果是空,返回相反的链表就是结果2.依次取出两个链表的值进行相加,如果不用进位,就依次插入下一个节点(newList.next=函数(l1.next,l2.next)) ,递归地调用),然后返回链表即可。3.如果计算进位,先算这一位进位后的结果newList;再计算下一位要加多少carry;其次在考虑不进位的条件下,下一位的结果current;最后把carry 和 current 做加和,也就是下一位数插入下一个节点(newList.next=函数(carry, curre

2020-05-24 11:23:48 782

原创 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。方案一:暴力求解直接进行嵌套循环比较两数的和是否为目标值如果是,对应值的下标此时时间复杂度因为进行嵌套循环,复杂度为O(n^2)/** * @param {number[]} nums * @param {number} target * @return {number[]} */var twoSum = function(nums, target) { f

2020-05-23 20:23:25 2455

原创 Java类集

Java类集引出类集实际上就属于动态对象数组,在实际开发之中,数组的使用出现的几率并不高,因为数组本身有一个最大的缺陷:数组长度是固定的。由于此问题的存在,从JDK1.2开始,Java为了解决这种数组长度问题,提供了动态的对象数组实现框架–Java类集框架。Java集合类框架实际上就是java针对于数据结构的一种实现。实际上链表的实现就是参考Java集合类实现的。Collection在Ja...

2018-12-11 12:59:04 197

原创 序列化与反序列化

序列化基本概念定义:将内存中保存的对象变为二进制数据流的形式进行传输或保存在文本中。实现:Java中类若要被序列化输出,该类必须实现Serializable接口。该接口是一个标识接口,表示该类具有序列化的功能。public interface Serializable {}序列化与反序列化操作要想实现序列化与反序列化的对象操作,需要使用io包提供的两个类ObjectOutputStr...

2018-12-10 15:31:57 175

原创 内存操作流&打印流&输入流(Scanner)

内存操作流定义:除了文件之外,IO操作也可以发生在内存中,发生在内存中的操作流称为内存流。文件流的操作里面一定会产生一个文件数据(不管后这个文件数据是否被保留)。如果现在需求是:需要进行IO处理,但是又不希望产生文件,这种情况下就可以使用内存作为操作终端。内存流也分为两类:字节内存流:ByteArrayInputStream、ByteArrayOutputStream字符内存流:Ch...

2018-12-08 18:33:05 580

原创 文件拷贝

转换流现在为止已经知道了两种数据流:字节流和字符流。实际上这两种流是可以进行互相转换处理的。OutputStreamWriter:将字节输出流变为字符输出流(Writer对于文字的输出要比OutputStream方 便)InputStreamReader:将字节输入流变为字符输入流(InputStream读取的是字节,不方便中文的处理)要想知道这两个类的实际意义,我们首先来看这两个类的...

2018-12-08 14:51:42 217

原创 Java I/O

IO的核心组成就是五个类(File、 OutputStream、InputStream、Reader、Writer) 一个接口(Serializable)File文件操作类在Java.io包之中,File类是唯一一个与文件本身操作(创建、删除、取得信息…)有关,与文件内容无关的的程序类。File类即可以描述真实文件,也可以是个文件夹File类使用File类的两种实例化方式:publ...

2018-12-07 16:06:33 153

原创 ClassLoader类加载器

Class类描述的是整个类的信息,在Class类中提供的forName()方法,这个方法根据ClassPath配置的路径进行类的 加载,如果说现在你的类的加载路径可能是网络、文件,这个时候就必须实现类加载器,也就是ClassLoader类的 主要作用。认识ClassLoader首先通过Class类观察如下方法: /** * Returns the class loader f...

2018-12-06 15:08:57 253

原创 反射

认识发射反射指的是对象的反向处理操作,根据对象倒推类的组成。既然是反向处理,我们先来观察一下&quot;正&quot;的操作。在默认情况下,必须要先导入一个包,而后才能产生类的实例化对象范例:观察正常处理import java.util.Date;public class Test { public static void main(String[] args) throws Exception{...

2018-12-05 15:20:46 675

原创 线程池

概念Java中的线程池(juc包下)是运用场景多的并发框架,几乎所有需要异步或者并发执行任务的程序都可以使用线程池。使用线程池的有三个优点:降低资源的消耗:通过重复利用已创建的线程降低线程创建和销毁带来来的消耗提高响应速度:当新任务到达时,任务可以不需要等待线程创建就可以立即执行提高线程的可管理性:使用线程池可以统一进行线程分配、调度与监控线程池的实现原理当一个Runnabl...

2018-11-24 20:35:23 172

原创 Condition的await和signal等待/通知机制

Condition简介任何一个java对象都天然继承于Object类,在线程间实现通信的往往会应用到Object的几个方法,比如 wait(),wait(long timeout),wait(long timeout, int nanos)与notify(),notifyAll()几个方法实现等待/通知机制。同样的, 在 java Lock体系下依然会有同样的方法实现等待/通知机制。从整体上来...

2018-11-24 17:50:17 297

原创 读写锁ReentranReadWriteLock

读写锁简介在并发场景中用于解决线程安全的问题,我们几乎会高频率的使用到独占式锁,通常使用java提供的关键字 synchronized或者concurrents包中实现了Lock接口的ReentrantLock。它们都是独占式获取锁,也就是在同一时刻只有一个线程能够获取锁。而在一些业务场景中,大部分只是读数据,写数据很少,如果仅仅是读数据的话并不会影响数据正确性(出现脏读),而如果在这种业务场...

2018-11-23 21:17:53 809

原创 ReentrantLock

ReentrantLock介绍ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。java关键字synchronized隐式支持重入性,synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。...

2018-11-22 22:03:10 131

原创 AQS详解

AQS简介在同步组件的实现中,AQS是核心部分,同步组件的实现者通过使用AQS提供的模板方法实现同步组件语义。AQS 则实现了对同步状态的管理,以及对阻塞线程进行排队,等待通知等等一些底层的实现处理。AQS的核心也包括了这些方面:同步队列,独占式锁的获取和释放,共享锁的获取和释放以及可中断锁,超时等待锁获取这些特性的实现,而这些实际上则是AQS提供出来的模板方法。同步队列当共享资源被...

2018-11-22 16:18:02 18675 4

原创 Lock体系

Lock简介锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。在Lock接口出现之前,java程序主要是靠synchronized关键字实现锁功能的,而JDK5之后,并发包中增加了lock接口,它提供了与synchronized一样的锁功能。虽然它失去了像synchronize关键字隐式加锁解锁的便捷性,但是却拥有了锁获取和释放的可操作性,可中断的获取锁以...

2018-11-22 13:48:13 427

原创 synchronized优化

序言在JDK1.5中,synchronized是性能低效的。因为这是一个重量级操作,它对性能大的影响是阻塞的是实现,挂起 线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性带来了很大的压力。相比之下使用Java 提供的Lock对象,性能更高一些。import java.util.concurrent.locks.Lock;import java.util.concurrent...

2018-11-16 18:41:07 5355 2

原创 synchronized 同步

同步问题的引出需求:多个线程同时卖票class MyThread implements Runnable { private int ticket = 10; @Override public void run() { while (this.ticket &amp;amp;amp;gt; 0) { try { ...

2018-11-14 19:54:13 985

原创 多线程常用操作

线程命名与取得多线程的运行状态是不确定的,所以对于多线程操作必须有一个明确标识出线程对象的信息,这个信息往往通过名称来描述。在Thread类中提供有如下的线程名称方法:class MyThread implements Runnable { @Override public void run() {}}public class TestThread { publi...

2018-11-14 15:15:57 609

原创 多线程的实现

继承Thread类实现多线程java.lang.Thread是一个线程操作的核心类。新建一个线程简单的方法就是直接继承Thread类,而后覆写该类中的 run()方法(就相当于主类中的main方法)package www.bit.java;class MyThread extends Thread { private int ticket = 100; @Override...

2018-11-12 14:46:23 176

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除