知识需要积累
打开有道云笔记, 在前端目录中已经有约 30 多篇来自工作中, 项目中或者书本中的知识点总结, 大概看了一些, 大部分都是 JavaScript 相关的知识点, CSS 不多, 这里筛选出一些来, 按照时间顺序汇总分享出来文章没有具体内容, 也没有章节顺序, 仅仅是一些知识点的碎片或者理论化的论点时间跨度较长, 可能有些知识已经过时或者本身总结过程中有错误或遗漏, 请指正
CSS
position 定位
static
正常布局行为, 即元素在文档流中当前的布局位置
top/right/left/bottom/z-index 值在 static 定位元素下无效
relative
会为元素预留空间元素先放置在未添加定位时的位置, 在不改变页面布局的前提下调整元素位置
对 table-* 元素无效
absolute
不为元素预留空间指定元素相对于最近的非 static 定位的父级元素偏移
绝对定位的元素可以设置外边距(margin), 且不会与其他边距合并
fixed
不为元素预留空间指定元素相对于视窗 viewport 来定位元素的位置
元素的位置在屏幕滚动时不会改变
fixed 属性会创建新的层叠上下文
当元素祖先的 transform 属性非 none 时, 容器就会相对于该祖先 (不是 viewport) 来定位
sticky (2018/03/18 补)
盒元素根据正常流计算, 然后相对于该元素在流中的 flow root(BFC)和最近的块级祖先元素定位
对 table 同 relative
当元素被 sticky 定位时, 后续元素的位置扔按照该元素未定位时的位置来确定
JavaScript
作用域和函数作用域
作用域是一套用来确定如何查找变量对象的规则
如果查找的目的是给变量赋值, 则会使用 LHS 查询
如果查找的目的是获取变量的值, 则会使用 RHS 查询
赋值操作会导致 LHS 查询,= 操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作
LHS 和 RHS 都会从当前作用域开始一级一级作用域的查找, 直到找到或者达到作用域的顶层
函数作用域的含义是指属于这个函数的全部变量都可以在整个函数的范围内使用及复用
函数申明和函数表达式之间最重要的区别是函数的名称标识符将会被绑定在何处
- //1. 申明
- function foo() {} // 可以直接调用 foo()
- //2. 表达式
- var bar = function barfunc() {} // 不可以直接调用 barfunc()
- //3. 自执行函数
- (function func(){
- ...
- })() //func 被隐藏
申明提升: 包括变量和函数在内的所有申明都会在任何代码被执行前首先被处理
定义申明是在编译阶段进行的
赋值申明是在执行阶段进行的
函数申明和变量申明都会被提升
函数的申明优先于变量(包括表达式)
变量申明, 如果名称已存在则跳过该申明(防止覆盖同名函数申明)
函数申明, 如果名称已存在则被新函数的引用覆盖
闭包
当函数能够记住并访问所在的词法作用域时, 就产生了闭包, 即使函数是在当前词法作用域之外执行的
闭包会阻止垃圾回收机制对其所在作用域的回收
闭包可以让函数可以继续访问定义时的词法作用域, 并一直保持着对其的引用
几个实现浅拷贝的方法
- // 数据源
- const array = [1, 2, 3, {a : 1, b : 2}, true, [1,2,3]]
- const object = {a : 1, b : 'string', c : function () {}, d : [1,2,3], f : true}
- Object.assign()
- //eg
- Object.assign([], array)
- Object.assign({}, object)
- Array.prototype.slice (仅针对数组)
- var arrClone = array.slice(0)
for ... in 循环
扩展运算符 (2017 年新增)
- let arrClone = [...array]
- let objClone = {...object}
原型
每个函数都有一个 prototype 属性, 该属性指向一个对象, 即原型对象
普通对象如 var a = {} 没有 prototype 属性
每个对象都有一个__proto__属性, 该属性指向其构造函数的原型对象, 通过这个属性, 让实例对象也能够访问原型上的方法
构造函数的 prototype 与所有实例对象的__proto__都指向原型对象, 而原型对象的 constructor 指向构造函数
通过字面量创建的对象都链接到 Object.prototype 上, 即 Object 的原型对象上
delete 关键字只能删除自身属性 / 方法, 不能删除原型链上的属性 / 方法
不能使用 delete 来删除 supper 上的属性(2017 年新增)
使用不同的方法来创建对象和生成原型链
语法结构对象
普通对象继承 Object.prototype 的属性
数组对象继承 Array.prototype 的属性
函数对象继承 Function.prototype 的属性
...
构造器创建的对象(new 操作符)
Object.create 创建的对象
Object.create 用来创建一个新对象, 新对象的原型对象就是调用该方法传入的第一个参数
尽量减少原型链上的查找
hasOwnProperty 是唯一处理属性且不会遍历原型链的方法可以使用 hasOwnProperty 来检查自身属性
如何确定 this 的指向
this 的指向, 是在函数被调用的时候确定的
在函数执行过程中, this 一旦被确定, 就不可更改了
在一个函数上下文中, this 由调用者提供, 由调用函数的方式来决定
如果调用者函数, 被某一个对象所拥有, 那么该函数在调用时, 内部的 this 指向该对象
如果函数独立调用, 那么该函数内部的 this , 则指向 undefined 但是在非严格模式中, 当 this 指向 undefined 时, 它会被自动指向全局对象
找到函数的调用者以及区分函数是否是独立调用就可以区分 this
new 关键字
new 关键字让构造函数具有了与普通函数不同的许多特点
声明了一个中间对象(即实例对象)
将实例对象的原型指向构造函数的原型
将构造函数的 this, 指向实例对象
返回实例对象
- // new 关键字的内部模拟实现
- function New (constructor) {
- // 声明一个中间对象, 即实例对象
- var instance = {}
- if (constructor.prototype !== null) {
- // 将实例的原型指向构造函数的原型
- instance.__proto__ = constructor.prototype
- }
- //res 为构造函数的执行结果, 通过 apply 将构造函数内部的 this 修改为当前的 instance 实例对象
- var res = constructor.apply(instance, Array.prototype.slice.call(arguments, 1))
- // 当构造函数中明确指定了返回对象时, 那么 new 的执行结果就是该返回对象
- if (res !== null && (typeof res === 'object' || typeof res === 'function')) {
- return res
- }
- // 否则返回当前的实例对象
- return instance
- }
JSON.stringify 的第二个参数
JSON.stringify 接收 3 个参数, 第二个参数一般容易被忽略, 参数二主要有以下 3 中用法
如果是函数, 则对象在序列化过程, 每个值的每个属性都会经过该函数处理该函数接收 key, value 两个参数
如果返回一个 Number, 转换成相应的字符串被添加入 JSON 字符串
如果返回一个 String, 该字符串被作为属性值加入 JSON 字符串
如果返回一个 Boolean, "true" 或者 "false" 被作为属性值被添加入 JSON 字符串
如果返回任何其他对象, 该对象递归地序列化成 JSON 字符串, 对每个属性调用 replacer 方法除非该对象是一个函数, 这种情况将不会被序列化成 JSON 字符串
如果返回 undefined, 该属性值不会在 JSON 字符串中输出(对数组无效, 将会转换为 null)
如果是数组, 则只有包含在这个数组中的属性值才会被序列化
如果是 null / 未提供, 则所有属性都会被序列化
call 要比 apply 快
call 和 apply 在运行时都会创建一个叫做 argList 的对象序列 call 只需要将参数一一放在这个序列中, 而 apply 的参数是数组, 则需要获得其中的每一个值再放入
柯里化
柯里化是指这样一个函数: 它接受函数 A 作为参数, 运行后能够返回一个新的函数 B, 并且 B 能够处理 A 剩余的参数
柯里化通用表达式
- var currying = function(fn) {
- var args = [].slice.call(arguments, 1);
- return function() {
- // 主要还是收集所有需要的参数到一个数组中, 便于统一计算
- var _args = args.concat([].slice.call(arguments));
- return fn.apply(null, _args);
- }
- }
柯里化特征
接收单一参数, 讲更多的参数通过回调函数来搞定
返回一个新函数, 用于处理所有想传入的参数
利用 call/apply/arguments 对象来收集参数
返回的这个函数正式用来处理收集起来的参数
来源: https://juejin.im/entry/5aae78bd6fb9a028b92cee0e