在学js的过程中,记录一些零碎的小知识,以便以后翻看。持续更新……
学习资料:JavaScript教程 以及 《你不知道的JavaScript》系列丛书
- localstorage:保存用户更改,可用于覆盖当前页面已修改的hash,避免浏览器刷新后更改信息丢失。(以后补充和cookie的区别)
- example.com/favicon.ico,favicon.ico用于获取当前网站的title图标
- 变量提升:JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
console.log(a) // undefined
var a = 1
- JavaScript 使用大括号,将多个相关的语句组合在一起,称为“区块”(block),对于var命令来说,JavaScript 的区块不构成单独的作用域(scope)。
{
var a = 1;
}
a // 1
在区块外部,变量a依然有效,ES6为了改变这种现状,引入了let:
{
let a = 1;
}
a // undefined
- 关于是否添加分号:尤雨溪的回答
总结下来就是一句话:一行开头是括号或者方括号的时候加上分号就可以了,其他时候全部不需要。 - 如果存在多重循环,不带参数的break语句和continue语句都只针对最内层循环。
- 语句的前面有标签(label),用于跳转到程序的任意位置,通常与break语句和continue语句配合使用,跳出特定的循环或者代码块。
- 七大数据类型:
- number
- string
- boolean
- undefined
- null
- symbol
- object
object细分为:object(狭义),array,function
- 三种类型准换的方法:typeof,instanceof,Object.prototype.toString
var obj = { }, arr = [ ]
typeof obj // object
typeof arr // object
arr instanceof Array // true
obj instanceof Array // false
typeof NaN // number
typeof Ifinity // number
typeof null // object
function f(){}
typeof f // function
数组或对象会先调用valueOf()获取原始值,然后调用toString()转化成字符串,然后调用Number()转成数字,Boolean类型也是调用Number()转化成数字。
参考:js面试题大坑——隐式类型转换
Number(null) // 0
5 + null // 5
Number(undefined) // NaN
5 + undefined // NaN
神代码:
(!(~+[])+{})[--[~+""][+[]]*[~+[]]+~~!+[]]+({}+[])[[~!+[]*~+[]]] = sb
- 如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true。
- undefined
- null
- false
- 0
- NaN
- " " 或 ' '
-
event.target 和 event.currentTaget的区别,以后整理为博客,先参考这篇
-
typeof valueOf instanceof的用法,区别,输出结果博客总结
-
js现阶段主要掌握用法:改变元素的class,比如添加和取消"active",具体的样式交给CSS
-
尽量不要用浏览器提供的API,容易出bug
-
nextSibling找兄弟的时候:记住nodeType的1,3状态。1是元素,3是文字以及各种空格回车制表符。不过更常用nextElementSibling
-
记住常用DOM操作的API,出博客
-
setInterval() clearInterval() setTimeout()
-
如果忘了使用new命令,直接调用构造函数会发生什么事?
这种情况下,构造函数就变成了普通函数,并不会生成实例对象。而且由于后面会说到的原因,this这时代表全局对象,将造成一些意想不到的结果。
-
运算符:見博客
-
当需要迅速先hide()再show()的时候,浏览器会自动合并这个操作,也就是忽略掉hide(),此时可以在hide()之后调用offset()来打断浏览器这一行为。因为offset()会计算当前CSS中涉及变量的偏移。
-
写轮播图时,宽高在HTML写死的原因:作为图片站位符,防止图片加载不均匀发生重排(re-layout),重排时图片倒退,会降低效率,很耗内存。
这个手段常用于页面性能优化。
-
状态机的编程思想:
-
指导思想:HTML、CSS和JS:内容、样式和行为分离:
即
- 不要用HTML控制样式(<center>...</center>)
- 不要用CSS控制行为(IE下的expression,效率低下)
- 不要用js控制样式(div.show(),会改变display;最好只用js更改class:$div.classList.add('disable'))
-
.one():为元素添加一个事件处理,只执行一次。
-
transitionend事件会在CSS transition结束后触发,无缝轮播中有用到。
-
“点击别处消失”的实现方法:(遮蔽罩?)
(1)点击元素自身处理
(2)用jq封装好的
-
dispatchEvent & fireEvent
-
如果是被点击的节点同时拥有捕获和冒泡,那么执行顺序和添加顺序一致;其他情况都是优先捕获。
mouseenter:鼠标进入一个节点时触发,进入子节点不会触发这个事件
mouseover:鼠标进入一个节点时触发,进入子节点会再一次触发这个事件
mouseout:鼠标离开一个节点时触发,离开父节点也会触发这个事件
mouseleave:鼠标离开一个节点时触发,离开父节点不会触发这个事件
- click事件指的是,用户在同一个位置先完成mousedown动作,再完成mouseup动作。因此,触发顺序是,mousedown首先触发,mouseup接着触发,click最后触发。
dblclick事件则会在mousedown、mouseup、click之后触发。
(1)clientX、clientY
点击位置距离当前body可视区域的x,y坐标
(2)pageX、pageY
对于整个页面来说,包括了被卷去的body部分的长度
(3)screenX、screenY
点击位置距离当前电脑屏幕的x,y坐标
(4)offsetX、offsetY
相对于带有定位的父盒子的x,y坐标
MouseEvent.offsetX属性返回鼠标位置与目标节点左侧的padding边缘的水平距离(单位像素)
(5)x、y
和screenX、screenY一样
- 键盘事件由用户击打键盘触发,主要有keydown、keypress、keyup三个事件,它们都继承了KeyboardEvent接口。
- keydown:按下键盘时触发。
- keypress:按下有值的键时触发,即按下 Ctrl、Alt、Shift、Meta 这样无值的键,这个事件不会触发。对于有值的键,按下时先触发keydown事件,再触发这个事件。
- keyup:松开键盘时触发该事件。
鼠标的事件属性。
onclick
ondblclick
onmousedown
onmouseenter
onmouseleave
onmousemove
onmouseout
onmouseover
onmouseup
onwheel
键盘的事件属性。
onkeydown
onkeypress
onkeyup
焦点的事件属性。
onblur
onfocus
表单的事件属性。
oninput
onchange
onsubmit
onreset
oninvalid
onselect
触摸的事件属性。
ontouchcancel
ontouchend
ontouchmove
ontouchstart
拖动的事件属性分成两类:一类与被拖动元素相关,另一类与接收被拖动元素的容器元素相关。
被拖动元素的事件属性。
ondragstart:拖动开始
ondrag:拖动过程中,每隔几百毫秒触发一次
ondragend:拖动结束
接收被拖动元素的容器元素的事件属性。
ondragenter:被拖动元素进入容器元素。
ondragleave:被拖动元素离开容器元素。
ondragover:被拖动元素在容器元素上方,每隔几百毫秒触发一次。
ondrop:松开鼠标后,被拖动元素放入容器元素。
<dialog>对话框元素的事件属性。
oncancel
onclose
- 当需要响应式布局时,不要用img标签,用 div 的 background 来设置图片,而且还可以加个懒加载什么的
background: transparent url(...) no-repeat center;
background-size: cover;
-
display: flow-root; // 只有一个作用,触发BFC
-
为什么 let 和 const 不存在变量提升呢?
这是因为在编译阶段, 当遇到变量声明时, 编译器要么将它提升至作用域顶部(var 声明), 要么将它放到 临时死区(temporal dead zone, TDZ), 也就是用 let 或 const 声明的变量. 访问 TDZ 中的变量会触发运行时的错误, 只有执行过变量声明语句后, 变量才会从 TDZ 中移出, 这时才可访问.
下面这个例子你能不能全部答对.
typeof null; // 'object'
typeof []; // 'object'
typeof someStr; // 'undefined'
typeof str; // Uncaught ReferenceError: str is not defined
const str = 'Yancey';
第一个, 因为 null 根本上是一个指针, 所以会返回 'object'. 深层次一点, 不同的对象在底层都表示为二进制, 在 Javascript 中二进制前三位都为 0 的会被判断为 Object 类型, null 的二进制全为 0, 自然前三位也是 0, 所以执行 typeof 时会返回 'object'.
第二个想强调的是, typeof 判断一个引用类型的变量, 拿到的都是 'object', 因此该操作符无法正确辨别具体的类型, 如 Array 还是 RegExp.
第三个, 当 typeof 一个 未声明 的变量, 不会报错, 而是返回 'undefined'
第四个, str 先是存在于 TDZ, 上面说到访问 TDZ 中的变量会触发运行时的错误, 所以这段代码直接报错.
-
javascript:void($={}) 使不能复制的页面可以复制(原理??)
-
浏览器渲染机制(reflow && repaint)
-
flex布局中,对需要右对齐的元素设置margin-left: auto即可
-
图片居中HTML5:
-
Object.assign 方法可以很方便地一次向类添加多个方法。
-
类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
上面代码中,toString 方法是 Point 类内部定义的方法,它是不可枚举的。这一点与 ES5 的行为不一致。
ES6 规定,在子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例。
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
上面代码中,super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()内部的this指向子类B的实例,导致输出的是2,而不是1。也就是说,实际上执行的是super.print.call(this)。
网友评论