标准盒模型javascript
对应 box-sizing: content-box; css
对应 box-sizing: border-box;html
一、父层加overflow:hidden;vue
二、父层添加:afterjava
.parent:after {
clear:both;
display:block;
content:'';
}
.parent {
*zoom:1;//为了兼容IE6/7
}
复制代码
三、添加一个空div,设置node
clear:both
复制代码
一、适合定宽的,水平居中react
{
marin:0 auto;
}
复制代码
二、绝对定位,定宽不定宽都适合,垂直居中webpack
{
position:absloute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
}
复制代码
{
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
margin:0 auto;
}
复制代码
三、flex (IE10及以上),垂直居中程序员
.parent{
display:flex;
justify-content:center;
align-item:center
}
复制代码
四、水平居中es6
.parent {
text-align:center;
}
.child{
display:inline-block;
}
复制代码
五、垂直居中
{
text-align:center;
line-height:20px;//line-height=height
}
复制代码
六、绝对定位,定高宽的
{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
margin-top:-50px;
margin-left:-50px;
}
复制代码
一、条件注释法
<!--[if !IE]><!--> 除IE外均可识别 <!--<![endif]-->
<!--[if IE]> 全部的IE可识别 <![endif]-->
<!--[if IE 8]> 仅IE6可识别 <![endif]-->
<!--[if lt IE 8]> IE8如下版本可识别 <![endif]-->
<!--[if gte IE 8]> IE8以及IE8以上版本可识别 <![endif]-->
复制代码
二、类内属性前缀法
一、float+margin-left
.left{
float:left;
width:200px;
}
.right {
margin-left:200px
}
复制代码
二、双inline-block/双float
.left{
width:200px;
}
.right{
width: calc(100% - 200px);
}
复制代码
三、float+bfc
.left{
float:left;
margin-right:20px;
}
.right{
overflow:auto;
}
复制代码
四、flex
.container {
disply:flex;
}
.right{
flex:1;
}
复制代码
<div class="container">
<div class="middle">测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
.container{
padding: 0 200px;
}
.middle{
width: 100%;
background: paleturquoise;
height: 200px;
float: left;
}
.left{
background: palevioletred;
width: 200px;
height: 200px;
float: left;
font-size: 40px;
color: #fff;
margin-left:-100%;
position: relative;
left:-200px;
}
.right {
width: 200px;
height: 200px;
background: purple;
font-size: 40px;
float: left;
color: #fff;
margin-left: -200px;
position: relative;
left:200px;
}
复制代码
二、用flex
在圣杯布局的基础上,在mian外面加一层main-container,在main 上设置margin:0 200px;
.middle-container{
width: 100%;
background: paleturquoise;
height: 200px;
float: left;
}
.middle {
margin:0 200px;
}
.left{
background: palevioletred;
width: 200px;
height: 200px;
float: left;
font-size: 40px;
color: #fff;
margin-left:-100%;
}
.right {
width: 200px;
height: 200px;
background: purple;
font-size: 40px;
float: left;
color: #fff;
margin-left: -200px;
}
复制代码
top是cpu经过计算来进行渲染的;translate是GPU计算渲染的,CPU能够同时作其余的一些计算;因此translate的性能优于top
animation-name 动画名称
animation-duration 动画时间
animation-timing-function 速度曲线,开始结束的方式
animation-delay 开始播放前的延迟时间
animation-iteration-count 播放次数
animation-direction 是否反向播放
复制代码
transition: property(css属性名) duration(时间) timing-function(速度曲线) delay(延迟时间);
一、包含浮动元素; 二、不被浮动元素覆盖; 三、阻止margin折叠的问题
offsetWidth/offsetHeight返回值包含content + padding + border,效果与e.getBoundingClientRect()相同
clientWidth/clientHeight返回值只包含content + padding,若是有滚动条,也不包含滚动条
scrollWidth/scrollHeight返回值包含content + padding + 溢出内容的尺寸
复制代码
一、!important,加在样式属性值后,权重值为 10000 二、内联样式,如:style=””,权重值为1000 三、ID选择器,如:#content,权重值为100 四、类,伪类和属性选择器,如: content、:hover 权重值为10 五、标签选择器和伪元素选择器,如:div、p、:before 权重值为1 六、通用选择器(*)、子选择器(>)、相邻选择器(+)、同胞选择器(~)、权重值为0
scss是sass的升级版,一、扩展名不一样,一个是以.scss 结尾,一个是以.sass结尾;二、sass有严格的缩进语法,且不带{}和;而scss须要{}和;,对空格也不敏感
解决办法:一、jsonp(只能get,没法适用于post)。原理:利用script标签没有跨域限制的“漏洞”来达到与第三方通信的目的
二、服务器端设代理;
三、后端在服务器上设置cors,在Access-Control-Allow-Origin中设置容许的请求源。cors请求分为简单请求和非简单请求。
若是是简单请求,浏览器会直接发送cors请求,即若浏览器发现此次跨域为简单请求,就会在头信息(Request Header)中添加一个Origin字段,表示本次请求来自于哪一个源。判断Origin是否在容许源(由服务端决定)范围以内,若是验证经过,服务端会在Response Header 添加 Access-Control-Allow-Origin(必选,表示服务器端容许的请求源)、Access-Control-Allow-Credentials等字段。浏览器收到Respnose后会判断本身的源是否存在 Access-Control-Allow-Origin容许源中,若是不存在,会抛出“同源检测异常”。
总结:简单请求只须要CORS服务端在接受到携带Origin字段的跨域请求后,在response header中添加Access-Control-Allow-Origin等字段给浏览器作同源判断。
非简单请求须要CORS服务端对OPTIONS类型的请求作处理,其余与简单请求一致
cookie/localStorage/sessionStorage
cookie: 可设置失效时间,没有设置的话,默认关闭浏览器后失效;
localstorage:除非手动删除,不然永久保存;
sessionstorage: 仅在当前网页会话下有效。关闭页面或浏览器会失效
cookie: 4kb左右;local~/session~:5mb左右
cookie每次都会携带在http头中,若是使用cookie保存过多的数据会带来性能问题;
local~/session~:仅在客户端(浏览器)中保存,不参与和服务器通讯
200 OK 请求没问题实体的主体部分包含了所请求的资源。
202 Accept 接受请求,处理还没有完成
204 no content 服务器成功处理了请求,但没有返回任何内容
304 not modified 未修改自动上次请求后,请求的网页未修改过。服务器返回此响应,不会返回网页的内容
400 错误请求 服务器不理解请求的语法
401 未受权 请求要求身份验证。对于须要登陆的网页,服务器可能返回此响应
403 禁止 服务器拒绝请求
404 未找到 服务器找不到请求的网页
405 方法禁用 禁用请求中指定的方法
500 服务器内部错误 服务器遇到错误,没法完成请求
501 还没有实施 服务器不具有完成请求的功能。例如,服务器没法识别请求方法时可能会返回此代码
HTTP缺点
通讯使用明文,可能被窃听
不验证通讯方的身份,可能遭遇假装
没法证实报文的完整性,有可能遭遇篡改
复制代码
https = http + TLS/SSL(具备身份验证、信息加密和完整性校验的功能)
HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性,加密数据包。
做用域链的做用是保证执行环境里有权访问的变量和函数是有序的,做用域链的变量只能向上访问,变量访问到window对象即被终止,做用域链向下访问变量是不被容许的 做用域就是变量与函数的可访问范围,即做用域控制着变量与函数的可见性和生命周期
每一个函数都有一个prototype属性,这个属性就是原型。原型链就是对象之间的继承链,一个对象经过的prototype指向一个父对象,父对象的prototype又指向另外一个对象,最终指向Object对象。这一个关系链就是原型链
1.对象有属性__proto__,指向该对象的构造函数的原型对象。 2.方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象
__proto__是每一个对象都有的一个属性,而prototype是函数才会有的属性!!!
JavaScript中的对象,都有一个内置属性[[Prototype]],指向这个对象的原型对象。当查找一个属性或方法时,若是在当前对象中找不到定义,会继续在当前对象的原型对象中查找;若是原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它本身的原型);如此继续,直到找到为止,或者查找到最顶层的原型对象(Object.prototype)中也没有找到,就结束查找,返回undefined。
原型链做用:对象属性的访问修改和删除。
访问。优先在对象自己查找,没有则顺着原型链向上查找
修改。只能修改跟删除自身属性,不会影响到原型链上的其余对象。
复制代码
闭包就是指有权访问另外一个函数做用域中的变量的函数,闭包的做用域链包含着它本身的做用域,以及包含它的函数的做用域和全局做用域。
闭包只能取得包含函数中任何变量的最后一个值,这是由于闭包所保存的是整个变量对象,而不是某个特殊的变量。
使用场景:一个是能够读取函数内部的变量,另外一个就是让这些变量始终保持在内存中,封装对象的私有属性和私有方法,实现对象的数据私有化;代替一些全局变量;
坏处:就是消耗内存、不正当使用会形成内存溢出的问题
function test(){
var arr = [];
for(var i = 0;i < 10;i++){
arr[i] = function(){
return i;
};
}
for(var a = 0;a < 10;a++){
console.log(arr[a]());
}
}
test(); // 连续打印 10 个 10
function test(){
var arr = [];
for(let i = 0;i < 10;i++){
arr[i] = function(){
return i;
};
}
for(var a = 0;a < 10;a++){
console.log(arr[a]());
}
}
test(); // 0-9
复制代码
缘由 :
函数1做用域
for(var i = 0; i < 10; i++) { 函数1做用域
我在函数1做用域中
arr[i] = function() { 函数2做用域
我在函数2做用域中
return i;
};
}
函数1做用域
console.log(i); 毫无疑问,执行到这里的时候,i是10,既然这里是10
那么在函数2做用域中访问i也是10也就不足为奇了
由于函数2做用域中没有,向上去函数1做用域中找
同一做用域中同一变量名的变量值确定是相同的(未修改的状况下)
复制代码
当你换成let的时候,读取i的时候,在当前做用域(块3)中没有找到,向上一个做用域(块2)寻找,在块2中发现i,因而拿到值。
块1做用域
for(let i = 0; i < 10; i++) { 块2做用域
我在块2做用域中
console.log(i); // 毫无疑问,这里的i从0依次增长到10
arr[i] = function() { 块3做用域
我在块3做用域中
return i;
};
}
块1做用域
复制代码
包括变量和函数在内的全部声明都会在任何代码被执行前首先
被处理
函数声明比变量声明优先提高
只有声明会被提高,变量的赋值或者其余运行逻辑会留在本地
复制代码
一、冒泡排序
function bubbleSort(arr){
for(var i=0;i<a.length;i++){
for(var j=0;j<a.length-i-1;j++){
var index;
if( a[j]>a[j+1]){
index = a[j];
a[j] = a[j+1];
a[j+1] = index;
}
console.log(a);
}
}
return arr;
}
复制代码
二、选择排序
function quickSort(arr){
var minIndex,temp;
for(var i=0;i<arr.length;i++){
minIndex = i
for(var j=i+1;j<arr.length;j++){
if( arr[j]<arr[minIndex]) {
minIndex = j;
}
}
if(i!=minIndex){
temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i]=temp
}
}
return arr
}
复制代码
三、统计字符串中次数最多字母
function findMaxDuplicateChar(str) {
if(str.length == 1) {
return str;
}
var charObj = {};
for(var i = 0; i < str.length; i++) {
if(!charObj[str.charAt(i)]) {
charObj[str.charAt(i)] = 1;
} else {
charObj[str.charAt(i)] += 1;
}
}
var maxChar = '',
maxValue = 1;
for(var k in charObj) {
if(charObj[k] >= maxValue) {
maxChar = k;
maxValue = charObj[k];
}
}
return maxChar + ':' + maxValue;
}
复制代码
四、数组去重 juejin.im/post/5aed61…
一、主线程运行的时候产生堆(heap)和栈(stack)
二、栈中的代码调用各类外部API,它们在"任务队列"中加入各类事件(click,load,done)
三、只要栈中的代码执行完毕,主线程就会去读取"任务队列",将队列中的事件放到执 行栈中依次执行。
四、主线程继续执行,当再调用外部API时又加入到任务队列中,等主线程执行完毕又会接着将任务队列中的事件放到主线程中。 上面整个过程是循环不断的。
事件队列(quene)是一个存储着待执行任务的队列,其中的任务严格按照时间前后顺序执行,排在队头的任务将会率先执行,而排在队尾的任务会最后执行。事件队列每次仅执行一个任务,在该任务执行完毕以后,再执行下一个任务。
堆:队列优先,先进先出;由操做系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操做方式相似于数据结构中的栈。
栈:先进后出;动态分配的空间 通常由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式却是相似于链表。
复制代码
值类型:boolen, string,number,null,undefined,symbol。保存在栈中,占用的空间规定。
引用类型:object,function。保存在堆中(引用变量存储在栈中的是一个指针,指向堆中的数组或者对象的地址),占用空间不固定
一、dom直接绑定:
在dom上直接绑定onclick、onmouseover、onmouseout等等。dom事件
二、在javascript代码中绑定:
在script标签中进行绑定
<input type="button" value="click me" id="btn">
<script>
document.getElementById("btn").onclick = function(){
alert("hello world!");
}
</script>
复制代码
三、使用事件监听绑定
关于事件监听,W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。
element.addEventListener(event, function, useCapture)
复制代码
event : (必需)事件名,支持全部DOM事件。
function:(必需)指定要事件触发时执行的函数。
useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。
优势:1.能够绑定多个事件。2.能够解除相应的绑定
四、关于事件委托
事件委托就是利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。
传统写法
<ul id="list">
<li id="item1" >item1</li>
<li id="item2" >item2</li>
<li id="item3" >item3</li>
</ul>
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
item1.onclick = function(){
alert("hello item1");
}
item2.onclick = function(){
alert("hello item2");
}
item3.onclick = function(){
alert("hello item3");
}
</script>
复制代码
事件委托
<ul id="list">
<li id="item1" >item1</li>
<li id="item2" >item2</li>
<li id="item3" >item3</li>
</ul>
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
document.addEventListener("click",function(event){
var target = event.target;
if(target == item1){
alert("hello item1");
}else if(target == item2){
alert("hello item2");
}else if(target == item3){
alert("hello item3");
}
})
</script>
复制代码
new Promise((resolved, rejected) => {
resolved(1);
}).then(data => {
console.log(data);
}, err => {
console.log(err);
}).catch(err => {
console.log(err);
}); // 1
复制代码
Promise解决了原先用ajax发送多个异步请求时,多层嵌套的一个问题,改成以.then()这种链式的形式进行屡次异步请求,更直观更方便维护。
Promise有3个状态:pending(进行中),fulfilled(成功),rejected(失败)
2个过程:pending———>fulfilled (resolve)请求成功 pending——>rejected (reject)请求失败
1个方法:.then()
Promise.all 用来包装多个异步请求,只有当里面全部请求都成功(resolve)时,才会被调用执行
Promise.race:也是用于将多个Promise实例包装成一个新的Promise实例,若是这个函数中,有一个Promise变成Fulfilled时,它就会将结果传递给下一个Promise
Promise.resolve:它会将一个当前对象转化为Promise对象
Promise.reject:返回一个出错的Promise对象
不会。当const 定义的是一个值类型时,修改会报错;当const定义的是一个引用类型(对象)时,修改不会报错
let是更完美的var,不是全局变量,具备块级函数做用域,大多数状况不会发生变量提高。const定义常量值,不可以从新赋值,若是值是一个对象,能够改变对象里边的属性值
关于变量提高
var a = 10;
function hello(){
console.log(a);//undefined
var a = 11;
console.log(a);//11
}
hello();
function hello(){
console.log(a);
let a = 11;
console.log(a);
}
hello();//报错:a is not defined
复制代码
一、箭头函数的this指向的事定义时所在上下文中的this,而不是使用时的对象;
二、不可以使用arguments对象,可使用扩展符...
三、不可以用做构造函数,这就是说,不可以使用new命令,不然就会抛出一个错误
遵循规范
require 是 AMD规范引入方式
import是es6的一个语法标准,若是要兼容浏览器的话必须转化成es5的语法
复制代码
调用时间
require是运行时调用,因此require理论上能够运用在代码的任何地方
import是编译时调用,因此必须放在文件开头
复制代码
本质
require是赋值过程,其实require的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量
import是解构过程,可是目前全部的引擎都尚未实现import,咱们在node中使用babel支持ES6,也仅仅是将ES6转码为ES5再执行,import语法会被转码为require
复制代码
模块输出时 export { onlyOne },对应引入时 import { onlyOne } form 。。。
export default 命令,为模块指定了默认输出,让他们不用阅读文档就能用任意自定义模块名加载模块。import “随意” form 。。。
es6.ruanyifeng.com/#docs/modul…
一、 isArray()
二、
三、instanceof 运算符是用来测试一个对象是否在其原型链原型构造函数的属性
var arr = [];
arr instanceof Array; // true
复制代码
四、constructor属性返回对建立此对象的数组函数的引用,就是返回对象相对应的构造函数
var arr = [];
arr.constructor == Array; //true
复制代码
async用于声明一个函数是异步的,async函数返回一个promise blog.csdn.net/lunahaijiao…
数组转字符串:join(),toString(), 字符串转数组:split()
ajax是一种异步请求数据的web开发技术,再不刷新页面的状况下,更新页面局部内容 ajax建立过程 step1. 建立XMLHttpRequest对象,也就是建立一个异步调用对象; step2. 建立一个新的HTTP请求,并指定改HTTP请求的方法、URL以及验证信息; step3. 设置响应HTTP状态变化的函数; step4. 发送HTTP请求; step5. 获取异步调用返回的数据; step6. 使用javascript和DOM实现局部刷新; www.imooc.com/article/352…
get/post区别
值类型(原始数据类型):Number String Boolean Undefined Null Symbol(es6) 引用类型:object (array function Date) 区别:值类型 保存在栈中, 引用类型保存在堆中,可是不能够直接访问堆内存空间中的位置和操做堆内存空间。只能操做对象在栈内存中的引用地址。引用对象的赋值其实是堆内存对象再栈中的引用地址复制,实际二者指向的是同一个堆内存对象
堆和栈是两种数据结构,堆是先进先出,栈是先进后出。
深浅拷贝是相对于引用类型来讲的 浅拷贝:子对象和父对象在浅拷贝的时候他们指向同一个内存的数组,因此子对象修改,父对象也会被修改 深拷贝:深度拷贝就是把父对象拷贝到子对象上,并且二者的内存和之后的操做都互不影响的拷贝 深拷贝方法一:
function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
复制代码
深拷贝方法二:
function deepCopy(obj){
var newobj, obj;
if (obj.constructor == Object){
newobj = new obj.constructor();
}else{
newobj = new obj.constructor(obj.valueOf());//valueOf()方法返回 Array 对象的原始值
}
for(var key in obj){
if ( newobj[key] != obj[key] ){
if ( typeof(obj[key]) == 'object' ){
newobj[key] = deepCopy(obj[key]);
}else{
newobj[key] = obj[key];
}
}
}
newobj.toString = obj.toString;
newobj.valueOf = obj.valueOf;
return newobj;
}
复制代码
== 只要求值相等,=== 是更严格的相等,要求值和类型都相等
MVC:用户操做->View(用户界面,负责接收用户的输入操做)->Controller(业务逻辑处理)->Model(数据保存,数据持久化)->View(将结果反馈给View)。
Virtual DOM是一个映射真实DOM的JavaScript对象,若是须要改变任何元素的状态,那么是先在Virtual DOM上进行改变,而不是直接改变真实的DOM。
react 和vue的一个区别:对于react而言,应用状态的改变会引发全部子组件的从新渲染,可是能够经过shouldComponentUpdate来控制子组件是否须要从新渲染。可是对于vue而言,这是一个默认的优化,它在渲染过程当中,会跟踪每个组件的依赖关系,不须要从新渲染整个组件树。因此它能够更快的计算出virtual dom的差别。
react的数据传递:
一、父到子:经过props传递;
二、子到父:父组件传一个callback回调函数给子组件调用,父组件定义一个函数看成props传递给子组件,在子组件中调用该函数,并将相关数据传进去,父组件中就能够拿到
三、同级之间的组件:先callback拿到其中一个子组件的数据,在经过props传给另外一个子组件
四、context
复制代码
const PropTypes = require('prop-types');
class Children extends React.Component {
static contextTypes = {
text: PropTypes.string
}
render() {
return (
<div>{ this.context.text }</div>
)
}
}
class Parent extends React.Component {
render() {
return (
<Children/>
)
}
}
class GrandParent extends React.Component {
static childContextTypes = {
text: PropTypes.string,
}
getChildContext() {
return {
text: 'Hi, my baby'
}
}
render() {
return (
<Parent text="Hi, my baby" />
)
}
}
复制代码
在 GrandParent 上经过 getChildContext 给 context 对象添加了 text 的属性,这个属性能够在 GrandParent 的任何一个子孙(子组件)中访问。
Redux 解决的是大型软件架构中数据流传输的问题;context 解决的是子孙之间方便数据交互的问题。有必定的类似性,但不属于同等性质。
三大原则:一、单一的数据源:整个应用的state都被储存在一棵树中,而且这棵状态树只存在于惟一一个store中;
二、只读的state:惟一改变state的方法就是出发一个action;
三、使用纯函数修改state:为每一个action用纯函数编写reducer来描述如何修改state树.reducer接受 Action 和当前 State 做为参数,返回一个新的 State。
纯函数:一、有传入的值就有返回的新值,二、不依赖外部的状态、变量或常量,三、不修改传入的值 store的职责:维持应用的 state;
提供 getState() 方法获取 state;
提供 dispatch(action) 方法更新 state;
经过 subscribe(listener) 注册监听器;
经过 subscribe(listener) 返回的函数注销监听器。
经过store.getState()来了解工厂中商品的状态,使用store.dispatch(接收action做为参数)发送action指令
react-redux 提供了两个重要的对象, Provider 和 connect ,前者使 React 组件可被链接(connectable),后者把 React 组件和 Redux 的 store 真正链接起来。
首先在最外层容器中,把全部内容包裹在 Provider 组件中,将以前建立的 store做为 prop 传给 Provider 。
const App = () => {
return (
<Provider store={store}>
<Comp/>
</Provider>
)
};
复制代码
Provider 内的任何一个组件(好比这里的 Comp ),若是须要使用 state 中的数据,就必须是「被 connect 过的」组件——使用 connect 方法对「你编写的组件( MyComp )」进行包装后的产物。
class MyComp extends Component {
// content...
}
const Comp = connect(...args)(MyComp);
复制代码
react-redux中的connect方法将store上的getState 和 dispatch包装成组件的props。
connect将方法和组件进行绑定。connect() 接收四个参数,它们分别是 mapStateToProps , mapDispatchToProps, mergeProps 和 options 。
第一个参数将 store 中的数据做为 props 绑定到组件上。
第二个参数将 action 做为props 绑定到 MyComp 上。 blog.csdn.net/u010977147/…
答案是:1
答案是: 1
以上两题,由于setState是异步的,他会先进入事件队列中等待,并非立刻出结果
webpack是把项目看成一个总体,经过一个给定的主文件(入口文件),webpack将从这个文件开始找到你的项目的全部依赖文件,使用loaders处理它们,最后打包成一个或多个浏览器可识别的js文件
核心:一、响应式的数据绑定系统(双向数据绑定);二、组建系统。 仔细看原理,戳我
经过Object.defineProperty( )实现对属性的劫持,给每一个属性对象都加上 setter和getter,已达到数据变更监听的目的,再结合发布者-订阅者,让多个观察者同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知全部观察者对象。
发布者发出通知 => 主题对象收到通知并推送给订阅者 => 订阅者执行相应操做
复制代码
减小重绘(repaint)和回流(reflow),回流指dom结构发生变化,或尺寸、布局发生变化,重绘指不影响布局的外观样式发生变化,如background-color.回流必定会引发重绘,重绘不必定引发回流