可拆分为 border-width,border-style,border-color3条属性
可以通过改变四条border的宽度实现特别的效果,比如:
div{
width: 100px;
height: 200px;
background: #fff;
position: absolute;
left: 0;
right: 0;
top:0;
bottom: 0;
margin: auto;
border-style: solid;
border-color: #000;
border-width: 1px 100px 1px 1px;
}
div{
width: 100px;
height: 200px;
background: #fff;
position: absolute;
left: 0;
right: 0;
top:0;
bottom: 0;
margin: auto;
border-style: solid;
border-color: #000;
border-width: 1px 100px 1px 1px;
border-radius: 50%;
}
用于制作圆角边框,border-radius 四个值对应左上,右上,右下,左下角分别是以对应值为半径的1/4圆弧
语法:box-shadow : h-shadow v-shadow blur spread color inset;
特殊用法:
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.3);
综合练习 : 实现分享图标
常见伪类 —— :hover :link :active :target :focus :visited
常见伪元素 —— ::before ::after ::first-letter ::first-line ::selection
::before和 ::after 伪元素
::before和::after下特有的content,用于在css渲染中向元素逻辑上的头部或尾部添加内容。
::before和::after必须配合content属性来使用,content用来定义插入的内容,content必须有
值,至少是空,还可以是string/attr()/url()/counter()。默认情况下,伪类元素的display是默认
值inline,可以通过设置display:block来改变其显示。
这些添加不会出现在DOM中,不会改变文档内容,不可复制,仅仅是在css渲染层加入。
所以不要用:before或:after展示有实际意义的内容,尽量使用它们显示修饰性内容,例如图标。
一般用于清除浮动、制作不规则图形及图标、多背景图
transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾
斜,一般常用的有旋转rotate(ndeg) 和 平移translate() ;需要注意的是它的坐标系是三维坐标
rotate
rotate是沿顺时针旋转的,并且在旋转的时候整个坐标系都会跟着一起转
rotate3d(x,y,z,angle)
(1).x:是一个0到1之间的数值,主要用来描述元素围绕X轴旋转的矢量值
(2).y:是一个0到1之间的数值,主要用来描述元素围绕Y轴旋转的矢量值
(3).z:是一个0到1之间的数值,主要用来描述元素围绕Z轴旋转的矢量值
(4).angle:一个角度值,指定在3D空间旋转角度,正值顺时针旋转,反之元素逆时
translate3d(x,y,z)
1.x:表示在x轴方向的位移
2.y:表示在y轴方向的位移
3.z:表示在z轴方向的位移
用法
/** 定义动画 */
@keyframes 动画名 {
from{
样式1...
}
to{
样式2...
}
}
/** 调用动画 */
div{
animation: 动画名 动画时间;
animation-iteration-count: infinite; // 动画重复次数
animation-timing-function: inherit; // 速度变化曲线
}
旋转八卦
跳动的心
爱心
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性
任何容器都可以指定为flex布局
.box{
display:flex;
}
行内元素也可指定为flex布局
.box{
display:inline-flex;
}
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
flex 骰子
立体骰子
this 是什么?this 既不指向函数自身,也不指函数的词法作用域,它实际是在函数被调用时才发生的绑定,也就是说this具体指向什么,取决于你是怎么调用的函数。
this 的4种绑定规则:
默认绑定、隐式绑定、显示绑定、new绑定。优先级从低到高
1、默认绑定:
function foo(){
console.log(this.a);
}
var a = 2;
foo(); // 打印结果?
foo() 打印的结果是2
因为foo()是直接调用的(独立函数调用),没有应用其他的绑定规则,这里进行了默认绑定,将全局对象绑定this上,所以this.a 就解析成了全局变量中的a,即2
注意:在严格模式下(strict mode),全局对象将无法使用默认绑定,即执行会报undefined的错误
function foo(){
“use strict”;
console.log(this.a);
}
var a = 2;
foo(); // Uncaught TypeError : Cannot read property 'a' of undefined
2、隐式绑定:
除了直接对函数进行调用外,有些情况是,函数的调用是在某个对象上触发的,即调用位置上存在上下文对象
function foo(){
console.log(this.a);
}
var a = 2;
var obj = {
a : 3,
foo : foo
}
obj.foo(); // ?
obj.foo() 打印的结果是3
这里foo函数被当做引用属性,被添加到obj对象上。这里的调用过程是这样的:
获取obj.foo属性 -> 根据引用关系找到foo函数,执行调用
所以这里对foo的调用存在上下文对象obj,this进行了隐式绑定,即this绑定到了obj上,所以this.a被解析成了obj.a,即3
当存在多层调用链时
function foo(){
console.log(this.a);
}
var a = 2;
var obj1 = {
a : 4,
foo : foo
}
var obj2 = {
a : 3,
obj1 : obj1
}
obj2.obj1.foo(); // ?
obj2.obj1.foo() 打印的结果是4
同样,我们看下函数的调用过程:
先获取obj2.obj1 -> 通过引用获取到obj1对象,再访问 obj1.foo -> 最后执行foo函数调用
这里调用链不只一层,存在obj1、obj2两个对象,那么隐式绑定具体会绑哪个对象。这里原则是获取最后一层调用的上下文对象,即obj1,所以结果显然是4(obj2.a)
3、显示绑定:
对隐式绑定,this值在调用过程中会动态变化,可是我们就想绑定指定的对象,这时就用到了显示绑定。
显示绑定主要是通过改变对象的prototype关联对象,这里不展开讲。具体使用上,可以通过这两个方法call(hellip;)或apply(hellip;)来实现(大多数函数及自己创建的函数默认都提供这两个方法)
call与apply是同样的作用,区别只是其他参数的设置上
function foo(){
console.log(this.a);
}
var a = 2;
var obj1 = {
a : 3,
foo : foo
}
var obj2 = {
a : 4,
obj1 : obj1
}
foo.call(obj1); // ?
foo.call(obj2); // ?
打印的结果是3, 4
这里因为显示的申明了要绑定的对象,所以this就被绑定到了obj上,打印的结果自然就是obj1.a 和obj2.a
4、new 绑定:
function foo(a){
this.a = a;
}
var a = 2;
var bar1 = new foo(3);
console.log(bar1.a); // ?
var bar2 = new foo(4);
console.log(bar2.a); // ?
最后一个打印是3, 4
因为每次调用生成的是全新的对象,该对象又会自动绑定到this上,所以答案显而易见
绑定规则优先级
上面也说过,这里在重复一下。优先级是这样的,以按照下面的顺序来进行判断:
函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。
函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是 指定的对象。
函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。
如果都不是的话,使用默认绑定。如果在严格模式下,就绑定undefined,否则绑定到全局对象。
规则例外
在显示绑定中,对于null和undefined的绑定将不会生效。
function foo(){
console.log(this.a);
}
var a = 2;
foo.call(null); // 2
foo.call(undefined); // 2
这种情况主要是用在不关心this的具体绑定对象(用来忽略this),而传入null实际上会进行默认绑定,导致函数中可能会使用到全局变量,与预期不符。
所以对于要忽略this的情况,可以传入一个空对象ø,该对象通过Object.create(null)创建。这里不用{}的原因是,ø是真正意义上的空对象,它不创建Object.prototype委托,{}和普通对象一样,有原型链委托关系
扩展:箭头函数
最后,介绍一下ES6中的箭头函数,通过ldquo;=>rdquo;而不是function创建的函数,叫做箭头函数。箭头函数中指向外层作用域的 this
var obj = {
foo(){
console.log(this);
},
bar : ()=>{
console.log(this);
}
}
obj.foo(); // {foo : f , bar : f }
obj.bar(); // window
Js new 分为四个过程:
模拟实现new方法
function Person(name){
this.name = name;
this.getName = function(){
console.log(this.name);
}
}
function New(){
var obj = new Object();
var Constructor = [].shift.apply(arguments); //取得该方法的第一个参数(并删除第一个参数),该参数是构造函数
obj.__proto__ = Constructor.prototype; //将新对象的内部属性__proto__指向构造函数的原型,这样新对象就可以访问原型中的属性和方法
var ret = Constructor.apply(obj,arguments); //取得构造函数的返回值 并将构造函数中的this指向新对象
return typeof ret=="object"? ret : obj; //如果返回值是一个对象就返回该对象,否则返回构造函数的一个实例对象
}
instanceof 用于判断一个变量是否是某个对象的实例
语法 : object instanceof constructor
参数:object(要检测的对象.)constructor(某个构造函数)
描述:instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上
instance_of : function(obj,f){
var a = obj.__proto__;
var b = f.prototype;
return a === b;
}
如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力
如何实现深复制:
1、递归复制
2、借用 JSON.stringify() 和JSON.parse()
3、JQuery 的 extend 方法 :
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上
object1 objectN可选 Object类型 第一个以及第N个被合并的对象
deepClone : function(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
DOM事件
事件流:事件流描述的是从页面中接收事件的顺序
DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
事件捕获阶段:实际目标div在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到html再到body就 停止了;
处于目标阶段:事件在div上发生并处理,但是事件处理会被看成是冒泡阶段的一部分;
冒泡阶段:事件又传播回document
div1
div2
div3
对于以上DOM,如果点击 div3 ,事件传播的顺序为:
1 document > 2 html > 3 body > 4 div1 > 5 div2 > 6 div3 > 7 div2 > 8 div1 > 9 body > 10 html > 11 document
1-5 为事件捕获阶段 , 6 为目标阶段 , 7-11 为事件冒泡阶段
JS 3种事件绑定方法及事件委托
事件绑定
嵌入dom
直接绑定
按钮
事件监听
按钮
事件委托
“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
事件委托的优点
(1)可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件就非常棒
(2)可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
例:
如果在一个复杂的 Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不 清的代码用于添加事件处理程序。此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示:
- 1
- 2
- 3
JS 时间循环机制
javascript从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初的用途来决定的:与浏览器交互
单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务
非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调
同步代码放入执行栈中从前往后执行,异步代码会先区分是宏事件还是微事件,
以下事件属于宏任务:
setInterval()
setTimeout()
以下事件属于微任务
new Promise() // 用.then() 或 .fetch() 来调用
new MutaionObserver()
我们只需记住当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
JS promise
Promise 对象代表一个异步操作,其不受外界影响,有三种状态:
- Pending(进行中、未完成的)
- Resolved(已完成,又称 Fulfilled)
- Rejected(已失败)
(1)promise 从未完成的状态开始,如果成功它将会是完成态,如果失败将会是失败态。
(2)当一个 promise 移动到完成态,所有注册到它的成功回调将被调用,而且会将成功的结果值传给它。另外,任何注册到 promise 的成功回调,将会在它已经完成以后立即被调用。
(3)同样的,当一个 promise 移动到失败态的时候,它调用的是失败回调而不是成功回调。
(4)对包含前进特性的实现来说,promise 在它离开未完成状态以前的任何时刻,都可以更新它的 progress。当 progress 被更新,所有的前进回调(progress callbacks)会被传递以 progress 的值,并被立即调用。前进回调被以不同于成功和失败回调的方式处理;如果你在一个 progress 更新已经发生以后注册了一个前进回调,新的前进回调只会在它被注册以后被已更新的 progress 调用。
(5)注意:只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
JS 时间循环机制
javascript从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初的用途来决定的:与浏览器交互
单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务
非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调
同步代码放入执行栈中从前往后执行,异步代码会先区分是宏事件还是微事件,
以下事件属于宏任务:
setInterval()
setTimeout()
以下事件属于微任务
new Promise() // 用.then() 或 .fetch() 来调用
new MutaionObserver()
我们只需记住当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
JS promise
Promise 对象代表一个异步操作,其不受外界影响,有三种状态:
- Pending(进行中、未完成的)
- Resolved(已完成,又称 Fulfilled)
- Rejected(已失败)
(1)promise 从未完成的状态开始,如果成功它将会是完成态,如果失败将会是失败态。
(2)当一个 promise 移动到完成态,所有注册到它的成功回调将被调用,而且会将成功的结果值传给它。另外,任何注册到 promise 的成功回调,将会在它已经完成以后立即被调用。
(3)同样的,当一个 promise 移动到失败态的时候,它调用的是失败回调而不是成功回调。
(4)对包含前进特性的实现来说,promise 在它离开未完成状态以前的任何时刻,都可以更新它的 progress。当 progress 被更新,所有的前进回调(progress callbacks)会被传递以 progress 的值,并被立即调用。前进回调被以不同于成功和失败回调的方式处理;如果你在一个 progress 更新已经发生以后注册了一个前进回调,新的前进回调只会在它被注册以后被已更新的 progress 调用。
(5)注意:只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。