caraws / review-javascript Goto Github PK
View Code? Open in Web Editor NEW复习js基础
复习js基础
在C或者其他语言数值的运算其实都是先将数值转换为二进制在做运算的,
而位运算符就是直接进行二进制运算, 因此速度会非常快. 但是对于JavaScript
来说, 执行环境一般接触不到硬件, 所以性能完全不能和其他语言相比. 不过作为
了解还是需要的, 只对较为常见的位运算符作记录.
位运算 NOT 由 ( ~ ) 符号表示, 其实就是对数值求负之后再减一, 如:
let num = 10;
let num2 = ~num;
// ~num 效果同下
num2 = -num - 1;
console.log(num2); // -11
左位移运算由 ( << ) 符号表示. 将数值的所有位向左移动指定数量.例如:
左移一位乘2, 左移2位乘4, 以此类推.
let num = 2;
let num2 = num << 2;
// 效果同下
num2 = num * 4;
console.log(num2); // 8
有符号右移运算符由 ( >> ) 符号表示, 将数值的所有为向右移动指定位数,
同时保留该数的符号 (正好或者负号) . 有符号右移运算符跟左位移运算符正好
相反.
let num = 12;
let num2 = num >> 2;
// 效果同下
num2 = num / 4;
console.log(num2) // 3
无符号运算符由 ( >>> ) 符号表示, 对于正数无符号右位移运算符跟无符号右位移
运算符规则相同; 负数时会出现无限大的数值, 所以决定使用无符号右位移运算符
时一定要小心.
var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
// charCodeAt() 方法可返回指定位置的字符的 Unicode 编码
u8arr[n] = bstr.charCodeAt(n);
}
// 'application/octet-binary' (默认值)
let blob = new Blob([u8arr], { type: mime })
使用atob 和 btoa 方法.
atob("amF2YXNjcmlwdA==")
// 解码结果 "javascript"
window.btoa(javascript)
// 转码结果 "amF2YXNjcmlwdA=="
以上两种方法对于中文是有局限性的, 解决如下:
var str = "China,**";
// 先用 encodeURI() 编码
window.btoa(window.encodeURIComponent(str))
// "Q2hpbmElRUYlQkMlOEMlRTQlQjglQUQlRTUlOUIlQkQ="
// atob 解码 Base64 再用 decodeURI() 解码
window.decodeURIComponent(window.atob('Q2hpbmElRUYlQkMlOEMlRTQlQjglQUQlRTUlOUIlQkQ='))
// "China,**"
17/9/4
快速排序的实现,,参考资料阮一峰
思路
快排法的**, 分为以下三步
var array = [11, 65, 23, 108, 99, 11, 55, 11, 33, 100, 108, 100];
console.time('快排');
const quickSort = array => {
// 数组只剩一个元素时停止
if (array.length <= 1) return array;
// 取参照物
let pivotIndex = Math.floor(array.length / 2),
// 这里用splice删除参照物避免重复循环
pivot = array.splice(pivotIndex, 1),
leftArr = [],
rightArr = [];
// 分区
for (let i = 0; i < array.length; i++) {
if (array[i] < pivot) {
leftArr.push(array[i]);
} else {
rightArr.push(array[i]);
}
}
return quickSort(leftArr).concat(pivot, quickSort(rightArr));
}
console.log(quickSort(array)); // [ 11, 11, 11, 23, 33, 55, 65, 99, 100, 100, 108, 108 ]
console.timeEnd('快排'); // 4ms 左右
console.time('快排2');
// 互换
const swap = (items, firstIndex, secondIndex) => {
let temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
}
// 分区
const partition = (items, left, right) => {
let pivot = items[Math.floor((right + left) / 2)],
i = left,
j = right;
while (i <= j) {
while (items[i] < pivot) {
i++;
}
while (items[j] > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j);
i++;
j--;
}
}
return i;
}
// 排序
const quickSortTwo = (items, left, right) => {
let index;
if (items.length > 1) {
left = typeof left != "number" ? 0 : left;
right = typeof right != "number" ? items.length - 1 : right;
index = partition(items, left, right);
if (left < index - 1) {
quickSortTwo(items, left, index - 1);
}
if (index < right) {
quickSortTwo(items, index, right);
}
}
return items;
}
console.log(quickSortTwo(array));
console.timeEnd('快排2');
console.time('原生');
array.sort((a, b) => {
if (a > b) return 1
else if (a < b) return -1
else return 0
});
console.log(array);
// 5ms 左右
console.timeEnd('原生')
两种方法, 当数组达到1W时差距就比较大了,原生需要17ms左右,原地快排需要13ms左右,而非原地快排则需要88ms左右。
17/9/7
模块
使用函数和闭包来构造模块. 模块是一个提供接口却隐藏状态与现实的函数或对象.
通过模块可以摒弃全局变量的使用, 模块模式的一般形式是: 一个定义私有变量和函数的函数;
利用闭包创建可以访问私有变量和函数的特权函数. -----<JavaScript语言精粹>
const serial_maker = _ => {
// 私有变量
let prefix = '';
let num = 0;
return {
// 特权方法
set_prefix: str => {
prefix = String(str);
},
set_num: n => {
num = +n;
},
get_sum: _ => {
let result = prefix + num;
num++;
return result;
}
}
}
let seqer = serial_maker();
seqer.set_prefix('Hi');
seqer.set_num(0101);
console.log(seqer.get_sum()) // 'Hi0101'
因为有了模块的概念, 所以我们能将很多重复性的代码封装成一个模块, 想用什么
功能就加载什么模块, 也能更方便是使用别人的代码. 但是这样就会要求大家都用
同样的方式封装模块, 所以就有了 CommonJs 和 AMD 来规范大家的写法.
var math = require('math');
math.add(2, 3);
require([module], callback);
require(['module'], module => {
module.increment(1, 2)
})
在JavaScript ES6中,export与export default均可用于导出常量/函数/文件/模块等,
以便在其它文件或模块中通过import将其导入使用.
// types.js
export const foo = 'foo';
export const fn = n => n+1;
// 在 index.html 引入
import {foo, fn} from 'types.js'
// types.js
export default const foo = 'foo';
// 在 index.html 引入
import foo from 'types.js'
// 等价于
import {default as foo} from 'types.js'
CSS
盒模型 (Box Model), 包含的要素分别为: content/padding/border/margin.
盒模型分为W3C的标准盒模型和IE的标准盒模型.
标准盒模型
content + padding+ border + margin
标准盒模型的 content 是不包含其他部分的, 如下图:
IE标准盒模型
content(padding + border) + margin
而IE标准盒模型的 content 已经包含padding和border的值, 如下图:
在文档顶部声明 DOCTYPE
就是为了让浏览器使用 W3C标准盒模型, 但是在 IE5/ IE6 下依然是 IE 标准盒模型. 当然通过box-sizing
属性可以在两者之间转换.
两个垂直方向相邻的块级元素相遇时, 外边距会合并且取值两者较大值的 margin
作为外边距.
解决方案: *{ margin: 0; padding: 0 }
margin 出轨...
当父元素没有 border
边框时, 第一个子元素添加 margin-top
会超出父元素, 相同最后一个子元素添加 margin-bottom
也同样会超出父元素, 如下图:
解决方案有四种:
- 给父元素添加 border.
- 给父元素添加 padding.
- 给父元素添加 overflow: hidden.
- 给父元素添加伪类. (最佳)
.parent { content: ''; display: table; }
2017-8-15
!!
操作符转换布尔值!!variable
来验证, class Foo {
constructor ( count ) {
this.cash = count;
this.myCash = !!count;
}
}
var emptyFoo = new Foo(0);
console.log(foo.cash); // 0
console.log(foo.myCash); // false
var foo = new Foo(100);
console.log(foo.cash); // 100
console.log(foo.myCash); // true
+
将字符串转换为数字var toNumber = strNumber => {
return +strNumber;
}
console.log( toNumber("123") ); // 123
console.log( toNumber(" abc")); // NaN
// Date也可以使用
console.log( +new Date() ); // 返回时间戳
if (isConcat) {
Login()
}
可以简写成这样 isConact && Login()
var arr = [1,2,3,4,5];
console.log( arr.slice(-1) ); // [5]
conosle.log( arr.slice(-2) ); // [4,5]
以此类推
array.length = 5
来截断数组, 如:var arr = [1,2,3,4,5];
console.log( arr.length); // 5
arr.length = 3;
console.log( arr.length ); // 3
console.log( arr ); // [1,2,3]
doucment.querySelectorAll('p')
获取元素, 它返回的是一个DOM元素的push() / sort()
等. 这就需要将这个 NodeList 转换为真正的数组.[].slice.call( NodeList )
来实现. 如:var els = document.querySelectorAll( 'p' );
[].slice.call( els );
OR:
var arrElement = Array.from( els );
ES6:
var arr = [...els]
var list = [1,2,3];
console.log(list.sort(()=>{ Math.random() - 0.5}))
17/6/14
有时候需要遍历后端返回的数据是数组中的数组, 可能是无限嵌套的情况.
比如: 查询省市区的情况, 需要判断当前选中的城市是否有子级.
if ( child == null || child.length == 0 ){
// 省市区只有三级
// area-code 是当前选中的地区编码
var length = area-code.length / 2;
// 现有城市数组
var array = areaList;
for ( var i = 0 ; i < length ; i++ ){
for ( el of array ){
if ( el.area-code == area-code.substr(i*2,2) ){
if ( i == length - 1 ){
delete el.children
return;
}else{
array = el.children;
break;
}
}
}
}
}
在预览摄像头监控画面时, 用socket发送RTSP实时视频流. 在浏览器中接收到是一堆bytes, 所以需要转化为blob类型或者base64给canvas渲染出来.
- Node端
当时用的是一个个人项目rtsp-ffmpeg
链接, 有空的话可以看看WebRTC
ffmpeg -version
出现版本号啥的就安装成功 ( 如果不行的话, ffmpeg的文件名换为FFMPEG就好, 不知道为啥就是要改下文件名; 或者重启 )
- 利用
socket.io
向浏览器发送视频数据
关键代码:
var rtsp = require('rtsp-ffmpeg');
// 推流
var uri = 'rtsp://accout:password@ip:port/h264/ch1/main/av_stream',
stream = new rtsp.FFMpeg({
input: uri,
rate: 10,
resolution: '320x240',
quality: 3
});
var cameraInfo = {}
io.on('connection', socket => {
console.log('connection')
var pipeStream = function(data) {
socket.emit('data', data);
};
stream.on('data', pipeStream);
socket.on('URI', data => {
console.log(data);
cameraInfo.cameraName = data.cameraName;
cameraInfo.groupName = data.groupName;
uri = `rtsp://${data.userName}:${data.passWord}@${data.ip}:${data.RTSP}/h264/ch1/main/av_stream`;
stream.input = uri;
stream.restart();
socket.emit('CameraInfo', cameraInfo);
})
socket.on('disconnect', function() {
stream.removeListener('data', pipeStream);
});
})
中间将Node.js
托管到IIS服务器上时会出现跨域的报错, 可能是和后端连接时端口被占, 具体看IIS报什么错. 如果IIS没报错, 还是有跨域的错重装一次socket.io
基本可以解决.
如果用canvas预览摄像头还是有花屏的情况, 可以将码流切换为子码流rtsp://accout:password@ip:port/h264/ch1/sub/av_stream
- 浏览器
基于Vue.js
, 先引入socket.io
并建立连接, 然后对视频流数据做处理(展示时不要用img
标签, 掉帧比较严重).
关键代码:
var bytes = new Uint8Array(data);
var blob = new Blob([bytes], {type: 'application/octet-binary'});
var url = URL.createObjectURL(blob);
var img = new Image;
var ctx = this.canvas.getContext("2d");
img.width = img.width * 0.5;
img.height = img.height * 0.5;
img.onload = function() {
URL.revokeObjectURL(url);
ctx.drawImage(img, 0, 0,720,560);
};
img.src = url;
2017/7/26
浅拷贝
浅拷贝只能拷贝顶层属性基本数据类型, 也就是如果父对象的属性是一个对象或数组, 那么子对象获取到的只是一个内存地址而不是一个真正的对象, 所以一旦修改父对象也会跟着被篡改.
function shallowCopy ( parent ) {
let o = {};
for (let i in parent) {
o[i] = parent[i]
}
return o
}
深拷贝
深拷贝也就是能够实现数组和对象拷贝, 深拷贝与浅拷贝对比, 深拷贝会在堆区开辟新的一块来储存新的对象. 两个对象对应的是两个不同的内存地址, 所以修改其中一个对象的属性并不会影响到另一个对象的属性. 实现深拷贝也有两种方式: 一种是递归/ 一种是JSON.
function deepCopy ( parent, child = {} ) {
for ( let i in parent ) {
if ( typeof parent[i] === 'object' ) {
child[i] = ( parent[i].constructor == Array ) ? [] : {};
deepCopy( parent[i], child[i])
} else {
child[i] = parent[i]
}
}
}
var o = {
age: '18',
friends: ['老张', '老王'],
job: {
main: '睡觉',
sub: '躺着'
}
};
var result = JSON.parse( JSON.stringify(o));
result.name = 'cara';
result.friends.push('老李');
console.dir(o);
console.dir(result)
通过JSON解析的方式不懂他的套路....
2017-8-15 18:38
继承
在那些基于类的语言, 继承是一种代码重用的形式, 如果一个新的类与一个已存
在的类拥有大部分相同的功能, 那么就只需要说明两者之间的区别即可. 但是
JavaScript 并没有类的概念, 但是有很多代码重用的模式, 它可以模拟类的
模式, 也可以支持其他的模式.
在 C++ 和 Java中都是用 new 命令来生成示实例, 在使用 new 命令时都会调用类的
构造函数(constructor), 因此 Brendan Eich ( JavaScript 作者)将 new 引入了 JavaScript,
从原型对象上生成一个实例对象. 因为 js 没有类, 所以在 new 命令后面跟的是构造函数,
而不是像 Java 一样跟的是类. 简单的来说就是通过构造器生产对象.
// 先扩展一个方法, 懒得每次打prototype
// 这个不是必须的
Function.prototype.method = (name, fn) => {
this.prototype[name] = fn;
return this
}
// 语言精粹里的例子 (其实这一步就是在模仿 new 的实现)
Function.method('new', _ => {
// 创建一个新对象, 它继承构造器函数的原型对象
let that = Object.create(this.prototype);
// 调用构造器函数, 将 this 绑定到新对象上
let other = this.apply(that, arguments);
return (typeof other === 'object' && other) || that
})
// 现在定义一个构造器
let Bar = name => {
this.name = name;
}
// 扩展这个构造函数的原型
Bar.prototype.get_name = _ => this.name;
Bar.prototype.say = _ => this.saying || '';
// 然后构造一个实例
let myBar = new Bar('妲己');
console.log(myBar.get_name()) // 妲己
/**
* 掩盖掉丑陋的 prototype
*/
// 借助一个辅助函数
Function.method('inherit', parent => {
this.prototype = new parent();
return this
})
// 重新定义一个构造函数
// 去继承上面的 Bar
let Foo = name => {
this.saying = 'wow';
}
// 这里 inherit 和 method 都直接返回 this
// 所以可以采用联级
.inherit(Bar)
.method('noise', _ => {
return this.name + this.say()
})
伪类模式在通过new 命令生产对象时, 会产生内存浪费. 如上面的例子, Foo 构造函数
就回去重复构造器 Bar 已经完成的工作.
在一个纯粹的原型模式中, 将摒弃类专注于对象. 基于原型的继承相比于类的
继承在概念上更为简单: 一个新对象可以继承一个旧对象的属性. 通过构造一个有用
的对象开始, 接着可以构造出更多和这个对象相似的对象. ----<JavaScript语言精粹>
// 先构造一个基础对象
const baseObject = {
name: 'base',
get_name: _ => this.name
}
// 接下来构造定制化的对象
let myObj = Object.create(baseObject);
myObj.name = 'wow';
myObj.saying = 'Hi';
myObj.purr = n => {
let str = '';
for (let i = 0; i < n; i++) {
if (s) {
str += 'hello'
}
str += 'world'
}
return str
}
这是一种'差异化继承', 通过制定一个新的对象, 指明它与基本对象的不同.
以上两种继承模式都没有实现私有化, 也就是说所有的变量和方法都是公开的, 所以就
可以开始运用模块模式. 这个函数主要分为四个步骤:
创建一个新的对象
定义私有属性.
给这个新对象扩充特权函数 (暴露接口)
返回这个对象
// spec 对象包含构造器所需要的所有信息
// my 对象允许其他构造器分享他们的私有属性
// 以便在我们的构造器中使用
let constructor = (spec, my) => {
let that = {}; // 私有实例变量
let my = my || {};
// 扩展共享的变量和方法
...
that = 一个新对象
// 给 that 添加特权方法
...
// 返回这个对象
return that
}
语言精粹里的例子
cosnt mammal = spec => {
let that = {};
that.get_name = _ => spec.name;
that.says = _ => spec.saying || '';
return that
}
let myMammal = mammal({name: 'Herb'});
let cat = spec =>{
spec.saying = spec.saying || 'meow';
// 继承
let that = mammal(spec);
that.purr = n => {
let i, s = '';
for (i = 0; i < n; i++) {
if (s) {
s += '-';
}
s += 'r';
}
return s
};
that.get_name = _ => {
return that.says() + ' ' + spec.name + ' ' + that.says();
}
return that
}
let myCat = car({name: 'Henrietta'});
以上函数化的方式还不能够调用父类的方法并向父类方法传递参数. 以下是测试代码
在语言精粹
的例子的基础上稍作改动, 便于自己理解:
// 构造器
const mammal = spec => {
let that = {};
that.get_name = _ => spec.name;
that.says = _ => spec.saying || 'Hi';
return that
}
let myMammal = mammal({name: 'Cara'});
console.log(myMammal.says()) // 'Hi'
// 构造器2
const cat = spec => {
spec.saying = spec.saying || 'meow';
// 此时 that 已经包含: get_name 和 says 方法
let that = mammal(spec);
that.purr = n => {
let str = '';
for (let i = 0; i < n; i++) {
if (str) {
str += '-';
}
str += 'r';
}
return str
};
that.get_name = n => {
return n || "i dont't have name"
};
return that
}
let myCat = cat({name: 'Henrietta'});
// i dont't have name
console.log(myCat.get_name())
// 这个时候 cat 还不能访问父类方法的能力
// 所以超类 super 还是有必要的
// 先扩展两个方法
// 这个方法不能用箭头函数来定义, 否则 this 指向的window
// 这里 this 需要的是被调用的对象
Function.prototype.method = function (name, fn) {
this.prototype[name] = fn;
return this
}
// 定义调用父类的函数
Object.method('superior', function (name) {
var that = this,
method = that[name];
return n => {
// this cat function
console.log(n)
return method.call(that, n);
};
})
// 来试试调用父类
const coolCat = spec => {
let that = cat(spec);
let super_get_name = that.superior('get_name');
// n 给父类方法传参
that.get_name = n => {
return 'like ' + super_get_name.call(this, n) + ' baby';
};
return that
}
let myCoolCat = coolCat({name: 'Bix', saying: 'Hi'});
let name = myCoolCat.get_name('this cat function');
console.log(name) // like this cat function baby
箭头函数的几个使用注意点:
函数体内的 this
对象, 就是定义时所在的对象, 而不是使用时所在的对象.
不可以当作构造函数, 也就是说, 不可以使用new命令, 否则会抛出一个错误.
因为箭头函数没有自己的 this
, 而是继承外层函数的this
.
不可以使用 arguments
对象, 该对象在函数体内不存在.
不可以使用 yield
命令, 因此箭头函数不能用作Generator函数.
在平时的布局中常常会用到的垂直水平居中. 下面就来总结几种垂直
水平居中的方法.
1. 绝对定位水平垂直居中
给元素设置绝对定位, 其父级元素为
body
或者指定的相对定位元素.
它的缺点是必须设置宽度值或者高度值; 优点是兼容性挺好, 代码也不
多, 不过听说在 windows phone 上不起作用.
<div class='wrapper'>
<div class='absolute-center'>我是绝对定位<div>
</div>
.wrapper{
width: 100%;
height: 200px;
position: relative;
border: thin solid black;
}
.absolute-center{
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
background: deepskyblue;
height: 100px;
line-height: 100px;
text-align: center;
color: #fff;
}
之前一直不懂绝对定位的工作机制到底是怎样, 下面是查资料看到的:
margin: auto
相当于margin-top: 0; margin-bottom: 0;
;position: absolute
会脱离文档流, 脱离的部分将不会影响文档流中的内容.top: 0; right: 0;bottom: 0;left: 0
, 浏览器将重新分配一个边界框, 这个时候的块区域会占满父级所有可用空间.margin: auto
.margin-top,margin-bottom
相同的值, 使元素块在先前定义的边界内居中.2. 可视区域内水平垂直居中
把上面例子改为
position: fixed; z-index: 999
, 设置一个较大值的z-index
; 如果不给这个块级元素设置宽高则会占满整个屏幕.
<div class="fixed-center">固定定位水平垂直居中</div>
.fixed-center{
width: 200px;
height: 200px;
position: fixed;;
z-index: 999;
background: rgba(0, 0, 0, .3);
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
line-height: 200px;
color: #fff;
text-align: center;
}
3. 边栏垂直居中
有时需要将一个内容块固定在屏幕的左侧或者右侧, 可以向内容快加入像这样的 CSS 代码
top: 20px; bottom: auto;
; 由于已经声明了margin: auto
, 内容块将会垂直居中在你定义的top
/right
/bottom
/left
边界值内. 可以用left: 0; right: auto
将内容快固定在左侧;right: 0; left: auto;
将内容固定在右侧.
<div class="absolute-left">
绝对定位在左侧
</div>
<div class="absolute-right">
绝对定位在右侧
</div>
.absolute-left {
position: absolute;
left: 20px;
right: auto;
margin: auto;
width: 150px;
height: 80px;
background: red;
color: #fff;
text-align: center;
line-height: 80px;
}
.absolute-right {
position: absolute;
left: auto;
right: 20px;
margin: auto;
width: 150px;
height: 80px;
background: green;
color: #fff;
text-align: center;
line-height: 80px;
}
4. 自适应绝对定位居中
自适应绝对居中的优势就是对百分比的宽高完美支持, 甚至是
max-width/ min-width
或者是max-height/ max-width
, 即使加上padding
也不会影响绝对居中的实现.
<div class="wrapper-responsive">
<div class="absolute-responsive">
自适应绝对定位居中
</div>
</div>
.wrapper-responsive{
position: relative;
top: 300px;
width: 200px;
height: 200px;
border: thin solid black;
}
.absolute-responsive{
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 60%;
height: 60%;
min-width: 50px;
max-width: 150px;
padding: 10px;
text-align: center;
color: #fff;
background: skyblue;
}
5. 内容溢出
有时内容块的内容过多导致高度大于父级元素, 内容就会显示到块和容器的外面, 这种时候加个给内容块
overflow: auto
即可, 如果内容块没有padding
的话加个max-height: 100%
也行.
6. 可变高度
设置
display: table
, 内容块会垂直居上不过水平还是居中. 但是这个在一些浏览器上有问题( 如: IE/ FF);display: table-cell
配合vertical-align: middle;
也可实现垂直水平居中.
<div class="wrapper-table">
<div class="table-center">
table 水平居中
内容内容内容内容内容内容内容内容内容内容内
</div>
</div>
<div class="wrapper-table-cell">
<div class="table-center-cell">
table-cell 居中
内容内容内容内容内容内容内容内容内容内容内
</div>
</div>
/* tabel 居中 */
.wrapper-table{
margin-top: 600px;
display: table;
height: auto;
width: 200px;
height: 200px;
border: thin solid black;
}
.table-center{
width: 80px;
background: orange;
color: #fff;
}
/* tabel-cell 居中 */
.wrapper-table-cell{
margin-top: 600px;
display: table-cell;
height: auto;
width: 200px;
height: 200px;
border: thin solid black;
vertical-align: middle;
}
.table-center-cell{
width: 100px;
background: #FFD34E;
color: #fff;
}
6. 负外边距
这个方法应该是很常用的方法了, 已知元素的宽高: 外边距
margin
的值取负数(没有box-sizing: border-box
的情况下, 包括padding
), 大小为width/ height
的一半, 再加上top: 50%; left: 50%
, 这个不能自适应哦.
<div class="wrapper-margin">
<div class="margin-center">
margin 居中
</div>
</div>
.wrapper-margin{
position: relative;
top: 100px;
border: thin solid black;
width: 200px;
height: 200px;
}
.margin-center{
width: 100px;
height: 100px;
background: #105B63;
position: absolute;
top: 50%;
left: 50%;
margin: -50px auto auto -50px;
color: #fff;
text-align: center;
line-height: 100px;
}
7. 变形
这可以说是最简单的方法了, 不仅可以实现绝对居中的想过还可以实现可变宽高度. 内容块定义
transform: translate(-50%, -50%)
带上浏览器前缀, 再加上top: 50%; left: 50%
即可.
<div class="wrapper-transform">
<div class="transform-center">
transform 居中
</div>
</div>
.wrapper-transform{
position: relative;
top: 200px;
border: thin solid black;
width: 200px;
height: 200px;
}
.transform-center{
width: 100px;
height: 100px;
background: #BD4932;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
color: #fff;
text-align: center;
}
8. Flexbox
CSS3的新属性也叫弹性盒子, 它不仅可以解决居中的问题还可以分栏或者其他的一些布局问题. 这里不多解释, 下次做一个详细的说明.
<div class="wrapper-flex">
<div class="flex-center">
弹性盒子居中
</div>
</div>
.wrapper-flex{
margin-top: 500px;
width: 200px;
height: 200px;
border: thin solid black;
display: flex;
justify-content: center;
align-items: center;
}
.flex-center{
background: grey;
color: #fff;
text-align: center;
}
2017-10-11 完
JavaScript包含了一套小型的可用在标准类型上的标准方法集,
主要是针对数组/正则及字符串的一些处理.
Array
concat 方法产生一个新的数组, 它包含的是一份 array 的浅复制
并把参数 item 追加在其后. 如果 item 是数组, 那么这个数组的
每个元素都会被添加.
let arr = [1, 2, 3];
let arr2 = [4, 5, 6];
let result = arr.concat(arr2, 'wow');
console.log(result); // [1, 2, 3, 4, 5, 6, 'wow'];
join 方法是把一个 array 以指定的分隔符构造成一个字符串.
它先把 array 中的每个元素构造成一个字符串, 然后以指定的
分隔符把它们都连接起来. 默认的 separate 是逗号, 可以用
空字符串作为 separate.
let array = ["a", "b", "c"];
array.push("d");
let result = array("|");
console.log(result); // "a|b|c|d"
pop 和 push 方法可以使 array 像堆栈一样工作. pop 方法移除数组
中的最后一个元素并返回该元素, 如果是空数组, 它将返回 undefined.
let arr = [1, 2, 3];
arr.pop()
console.log(arr); // 3
push 方法向数组的末尾添加一个或多个元素. 和 concat 方法不同的是,
他会修改 array, 如果 item 是一个数组, 会将整个参数数组作为一个元素
添加到 array 的末尾, 并返回这个新数组的长度.
let array = [1, 2, 3];
let arr = [4, 5, 6];
let result = array.push(arr. 'Hi');
console.log(result);
// array: [1, 2, 3, [4, 5, 6], 'Hi']
// result: 5
reverse 方法反转数组元素的顺序, 并返回数组本身.
let array = [1, 2, 3];
let result = array.reverse();
console.log(result); // [3, 2, 1]
shift 方法移除数组中的第一个元素并返回该元素. 如果是空数组
将会返回 undefined. shift 通常比 pop 慢得多.
let array = [1, 2, 3];
let result = array.shift();
console.log(result); // 1
slice 方法是截取 array 中的一段做浅复制. 复制 array[start] 开始
到复制 array[end]为止. end 参数是可选的, 默认值的长度是 array.length.
如果 start 的值大于等于 array.length, 会得到一个新的空数组.
let array = [1, 2, 3];
let a = array.slice(0, 1); // [1]
let b = array.slice(1); // [2, 3]
let c = array.slice(-1); // [3]
sort 方法是对数组中的元素排序,但他的默认比较函数是把被排序的元素都视为
字符串。 所以通常都是自己定义比较函数.
// 对字符串和数字排序
const compare = (a, b) => {
if (a === b) {
return 0
}
if (typeof a === typeof b) {
return a < b ? -1 : 1
}
return typeof a < typeof b ? -1 :1
}
let array = ['bb', 'aa', 2, 'cc', 3, 1, 7];
console.log(array.sort(compare())); // [ 1, 2, 3, 7, 'aa', 'bb', 'cc' ]
稳定性:排序后2个相等键值的顺序和排序之前它们的顺序相同.
const by = name => {
// o/p 每组相比较的数据
return (o, p) => {
let a, b;
if(o && p && typeof o === 'object' && typeof p === 'object') {
a = o[name];
b = p[name];
// 全等时
if (a === b) {
return 0
}
// 同类型
if (typeof a === typeof b) {
return a < b ? -1 : 1
}
// 不同类型
return typeof a < typeof b ? -1 : 1
}else {
console.log('排序失败')
}
}
}
let s = [
{first: 'Joe', last: 'DeRita'},
{first: 'Moe', last: 'Howard'},
{first: 'Joe', last: 'Besser'},
{first: 'Shemp', last: 'Howard'},
{first: 'Larry', last: 'Fine'},
{first: 'Curly', last: 'Howard'},
]
console.log(s.sort(by('first')).sort('last'));
/*
[
{ first: 'Curly', last: 'Howard' },
{ first: 'Joe', last: 'DeRita' },
{ first: 'Joe', last: 'Besser' },
{ first: 'Larry', last: 'Fine' },
{ first: 'Moe', last: 'Howard' },
{ first: 'Shemp', last: 'Howard' }
]
*/
// 让函数接收两个参数, 当第一个函数相等时
// 由第二个参数再次比较, 第二个次要比较函数可选
const betterBy = (name, minor) => {
return (o, p) => {
let a, b;
if (o && p && typeof o === 'object' && typeof 'object') {
a = o[name];
b = p[name];
if (a === b) {
// 用次要比较函数再次对比
return typeof minor === 'function' ? minor(o, p) : 0
}
if (typeof a === typeof b) {
return a < b ? -1 : 1
}
return typeof a < typeof b ? -1 : 1
}else {
console.log('排序失败');
}
}
}
let a = [
{first: 'Joe', last: 'DeRita'},
{first: 'Moe', last: 'Howard'},
{first: 'Joe', last: 'Besser'},
{first: 'Shemp', last: 'Howard'},
{first: 'Larry', last: 'Fine'},
{first: 'Curly', last: 'Howard'},
];
console.log(a.sort(by('last',by('first'))));
/*[
{ first: 'Joe', last: 'Besser' },
{ first: 'Joe', last: 'DeRita' },
{ first: 'Larry', last: 'Fine' },
{ first: 'Moe', last: 'Howard' },
{ first: 'Shemp', last: 'Howard' },
{ first: 'Curly', last: 'Howard' }
]
*/
splice 方法从 array 中移除一个或多个元素, 并用新的 item 替换他们.
start 是从 array 中移除元素的开始位置 ( 索引 ) , deleteCount 是要
删除元素的个数, item 参数如果有会被插入到被删除元素的位置上. 返回
被删除的元素.
let arr = ['b', 'a', 'c', 'bug'];
let remove = arr.splice(1, 1, 'newItem', 'Hi');
console.log(arr); // ['b', 'newItem', 'Hi','c', 'bug']
console.log(remove); // ['a']
unshift 方法向数组的开头插入一个或多个元素并返回数组新的长度.
let arr = ['a', 'b', 'c'];
let insert = arr.unshift('Hi', 'd');
console.log(arr); // ['Hi', 'd', 'a', 'b', 'c']
console.log(insert); // 5
RegExp
exec 方法是使用正则表达式的最强大(最慢)的方法. 如果它成功匹配
regexp 和字符串 string, 将返回一个数组. 数组中下标为0的元素包含
正则表达式 regexp 匹配的子字符串; 下标为1的元素是分组1捕获的文本;
下标为2的元素是分组2捕获的文本, 以此类推. 如果匹配失败则返回null.
test 方法是使用正则表达式的最简单(最快)的方法. 如果该regexp 与 string
匹配, 它返回 true, 否则返回 false. 不要对这个方法使用 g 标识.
let b = /&.+/.test('frank & beans');
console.log(b); // true
String
charAt 方法返回在 string 中 pos 位置处的字符串. 如果 pos 小于0或者
大于等于字符串的长度, 将返回空字符串.
let name = 'Cara';
let initial = name.charAt(0);
console.log(initial); // 'C'
concat 方法把其他字符串连接起来返回一个新的字符串. 通常用+
indexOf 方法在 string 内查找另一个字符串 searchString. 如果被
找到返回第一个匹配字符串的位置, 否则返回-1. 可选参数 position
可设置从 string 的某个指定位置开始查找.
let text = 'Mississippi';
let p = text.indexOf('ss'); // 2
p = text.indexOf('ss', 3); // 5
lastIndexOf 跟 indexOf 方法相反, 是从数组的末尾开始查找.
返回一个指定的字符串值最后出现的位置, 在一个字符串中的指定位置从后向前搜索.
let text = 'Mississippi';
let p = text.lastIndexOf('ss'); // 5
p = text.lastIndexOf('ss', 3); // 2
p = text.lastIndexOf('ss', 6); // 5
match 方法让字符串和一个正则表达式进行匹配. 它依据g
标识符来决定如何
进行匹配. 如果没有g
标识符, 那么调用 string.match(regexp)
的结果与
调用regexp.exec(string)
的结果相同. 如果有g
标识符, 那么它返回一个
包含所有匹配项(除捕获分组)的数组.
replace 方法对 string 进行查找和替换操作, 并返回一个新的字符串. 参数
searchValue 可以是一个字符串或者一个正则表达式对象. 如果是一个字符串,
那么 searchValue 只会把第一次匹配的出现的地方替换掉; 如果是正则表达式
带有g
标识符, 则会替换点所有匹配项.
let str = '1-10-1001';
let reg = /-(\d+)-/;
str.replace(reg, '栋$1单元');
console.log(str); // 1栋10单元1001
search 方法和 indexOf 方法类似, 只是它只接受一个正则表达式对象作为参数
而不是一个字符串. 如果找到匹配, 它返回第一个匹配的首字符位置. 如果没有
返回-1. 此方法会忽略g
标识符.
slice 方法复制 string 的一部分构造成一个新的字符串. 如果 start 参数是负数
, 他将与 string.length 相加. end 参数是可选的, 默认是 string.length. 如果
end 参数是负数, 也会与 string.length 相加. end 参数等于你想取的最后一个字符
的位置加1.
// str.length == 39
let str = 'and in it he says "Any damn fool could';
let a = str.slice(0, 3); // 'and'
let b = str.slice(-5); // 'could'
split 方法把 string 以指定的分隔符构造成一个字符串数组. 可选参数
limit 可以限制被分割片段的数量. separator 可以是一个字符串或者一个
正则表达式. 此方法会忽略g
标识符.
let str = '0123456789';
let a = str.split('', 5);
console.log(a); // ['0', '1', '2', '3', '4']
substring 方法和slice
方法一样, 只是不能处理负数. 所以用slice
代替它
toLocaleLowerCase 方法返回一个新的字符串, 它使用本地化的规则把这个 string
中的所有字母转换为小写格式.
toLocaleUpperCase 方法返回一个新的字符串, 它使用本地化的规则把这个 string
中的所有字母转换为大写格式.
17/9/21
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.