Open HTML50 opened 7 years ago
前几天写issues-comment的时候,在一台xp上测试页面报错,定睛一看,是login()方法未定义。
翻开代码一看,对象{ ... }内部的login()方法忘记写成login : function(){ ...}
,而是直接写成了login(){ ... }
,但是在自己电脑的chrome上并未任何报错。今天发现,这是ES6的新特性:对象字面量的简写,对于方法可以直接像这样写方法名。除此之外,还有好多其他新的特性,比如方法名可以动态生成了。
var obj = {
// __proto__
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’
handler,
// Method definitions
toString() {
// Super calls
return "d " + super.toString();
},
good(){
console.log('cool')
},
// Computed (dynamic) property names
[ 'prop_' + (() => 42)() ]: 42
};
今天在看严格模式(use strict),想起来之前遇到的函数内部声明函数报错的问题,顺手测试了一下,发现chrome Version 61.0.3163.79 已经不报错了。估计是又支持这样的函数声明了。interesting!
'use strict'
if(true){
function g(){
console.log('inner');
}
g();
}
for (var i = 0; i < 5; i++){
function f2() { }
f2();
}
function test(){
function gg(){
console.log(1);
}
console.log(2);
}
test()
看两个代码:
<div>div block element
<span> I am a child span in P
<p>child p in span</p>
</span>
</div>
<p>p block element
<span> I am a child span in P
<div>child div in span</div>
</span>
</p>
第一个代码生成的结构是符合预期的。
第二个就不行,p
标签内不能再包含有block
元素,在遇到block
元素前会自动闭合。
今天逛论坛看见有人问:为什么注释的滚动执行不了
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="test" style="height: 3000px"></div>
</body>
<script>
setTimeout(function () {
window.scrollTo(0, 3000)
});
//window.scrollTo(0, 3000)
</script>
</html>
我随手粘贴到Sublime里面,把注释去掉,用Chrome测试了一下,果然没反应。
想了想,以为是CSS,JS执行顺序的关系,还专门复习了一下DOM渲染过程。最终也没找到原因。
最后有人说了是Chrome滚动条管理的问题,会记住刷新时的位置,Firefox就没问题。
我想到之前写BLOG时遇到的history.scrollRestoration = 'manual'
,手动管理滚动条。
加上这句之后,刷新就可以滚动了。
明白为什么之后,我还专门测试了一下Chrome和Firefox在这点的不同。
设定body
高度为1000px
,先向下拖动滚动条一段距离,Ctrl+F5刷新后,在Chrome中滚动条是不动的,在FF中,滚动条会回到顶部。
另外有个有趣的现象,在一个body有若干<p>
的页面内,将滚动条拖动到距离顶部一定距离,每次刷新Chrome都会向下滚动一小段距离,直到<p>
标签内容都滚动出可视范围才会停止。
Array.forEach
Array.map
Array.filter
Array.some
Array.every
Array.reduce
js麻烦的一点在于很多内置函数但是返回的结果没有什么规律,有的返回一个值,有的返回一个数组。
对于上面这几个函数我也用了好多遍了,但总是使用时还要再看一眼文档。今天给这些方法归下类,方便记忆。
let arr = [1,2,3,4,5,6,7]
//用于演示的数组
forEach是遍历,和for in
差不多一样。
let result = arr.forEach((v)=> console.log(v))
//1,2,3,4,5,6,7
console.log(result)
//undefined,不返回内容
map,filter返回的都是数组。
result = arr.map((v)=> v*2)
console.log(result)
//[2,4,6,8,10,12,14]
result = arr.filter((v)=> v>7)
console.log(result)
//[8,10,12,14]
reduce比较有意思,我的理解是,reduce是减少的意思,每次把数组前一个项和后一项一起进行次运算,然后把前一项扔掉,后一项变为运算后的值,以此递减,直到最后的值。
result = arr.reduce((p,n) => p+n)
console.log(result)
//28
some,every从字面可以理解,部分和全部满足一定条件,返回true或false。
result = arr.some((v) => v>6)
console.log(result)
//true
result = arr.every((v) => v>6)
console.log(result)
//false
好了,就这几个。以后应该记得很清楚了。
今天写代码时遇到个this
的小问题。
大家都知道,在setTimeout,addEventListener
的function
中,this
的指向一般是window
。
看下面代码的两个输出:
function User(username) {
this.username = username;
this.sayHi = function() {
console.log(this.username);
}
}
var user = new User('John');
setTimeout(user.sayHi, 1000);
//undefined
setTimeout(function() {
user.sayHi();
}, 1000);
//John
说出来不怕笑话,快写了一天代码了,愣是在这里绕不出来了。
仔细想了半天,才明白第一个setTimeout
那里,user.sayHi
有点指针的意思,指向了对应的函数,相当于:
setTimeout(function() {
console.log(this.username);
}, 1000);
故得到window.username
为undefined
。
var a = {n:1};
var b = a;
a.x = a = {n:3}
console.log(a.x,a)
var t = true;
window.setTimeout(function (){
t = false;
},1000);
while (t){}
alert('end');
<div id="test" class="good">1</div>
<div id="test" class="good">2</div>
<div id="test" class="good">3</div>
document.getElementById('test')
document.querySelector('#test')
只能得到第一项,即<div id="test" class="good">1</div>
但是:
document.querySelector('.good')
也只能得到包含class=good
的第一项。
想要查询多个,需要:
document.querySelectorAll('.good')
此时,
document.querySelector('#test')
也查询到多个#test
。
可见,ID在HTML中的唯一与否,在正确查询的基础上,基本没有使用上的影响。
今天写页面时遇到几个正则的问题。
1.flags值 es6之前是m g i三种,es6又添加了y u两种模式。 我在chrome v64上使用的是s模式(单行模式?),到v60就报错了。粗略研究了一下es8没找到s模式的内容,但估计已经得到了浏览器的支持。
2.匹配任意内容
/[\.\n]*/g
在[]
内貌似\.
是无效的,只能用[\s\S]*
代替。
3.new RegExp()
/\s*/g
与new RegExp('\s*','g')
是不一样的,使用new
时需要双重转义:new RegExp('\\s*','g')
,要有两个\
。
var stopTime = new Date().valueOf() + 2000;
setTimeout(function(){
console.log('setTimeout 0ms 1')
},0)
console.log('start running while section 1')
console.time('while section1 job done')
while(new Date() < stopTime){}
console.timeEnd('while section1 job done')
console.log('start running while section 2')
console.time('while section2 job done')
setTimeout(function(){
console.log('setTimeout 0ms 2')
},0)
stopTime = new Date().valueOf() + 1000;
while(new Date() < stopTime){}
console.log('')
console.timeEnd('while section2 job done')
setTimeout(function(){
console.log('setTimeout 0ms 3')
},0)
上面的代码执行结果是:
start running while section 1
while section1 job done: 1999ms
start running while section 2
while section2 job done: 1000.58ms
setTimeout 0ms 1
setTimeout 0ms 2
setTimeout 0ms 3
1.最初我想巩固一下JS单线程的知识点,设计了一个while
循环,并且在while
前设定了一个setTimeout
为0的输出。
var stopTime = new Date().valueOf() + 2000;
setTimeout(function(){
console.log('setTimeout 0ms 1')
},0)
while(new Date() < stopTime){}
如果while
判断条件永远为true
,那么延时输出是肯定执行不了的,因为单线程被阻塞了。于是我把while
条件设定为日期比较的形式,只阻塞几秒钟,然后就可以得到输出。
2.然后我就想到,这个延时为0的输出是不是应该立马在阻塞后执行呢。
按照上面的代码,是这样的。于是我在while
之后加上了一大堆无意义的输出(字符串,打印当前时间等):
var stopTime = new Date().valueOf() + 2000;
setTimeout(function(){
console.log('setTimeout 0ms')
},0)
while(new Date() < stopTime){}
console.log(new Date())
console.log(new Date())
console.log(new Date())
console.log(new Date())
...
...
...
console.log(new Date())
//重复n多次
输出的结果是:
一大堆输出
...
...
...
一大堆输出
setTimeout 0ms
延时执行输出是在最后一行出现。我就很困惑:while
执行已经阻塞了线程这么长时间,执行完毕后应该先执行setTimeout
里的输出了吧!
这么多的一次次输出,整个执行难道都是连续的看作一个任务吗?(其实有经验的JSer已经能看出来了,这里无意义的输出,或者说除了setTimeout
外的代码,一个页面内所有的script内容,都属于一个完整的任务,并不能把每行分开来看)
于是我在困惑中挣扎良久,就有了最开篇的试验代码,包括下面的试验:
var stopTime = new Date().valueOf() + 2000;
setTimeout(function(){
console.log('setTimeout 2000ms')
},2000)
//注意这里是2秒后执行
console.log('start running while section 1')
console.time('while section1 job done')
while(new Date() < stopTime){}
console.timeEnd('while section1 job done')
setTimeout(function(){
console.log('setTimeout 0ms 2')
},0)
//while之后,立马加入一个0秒后的队列任务
console.log('start running while section 2')
console.time('while section2 job done')
stopTime = new Date().valueOf() + 1000;
while(new Date() < stopTime){}
console.log('')
console.timeEnd('while section2 job done')
setTimeout(function(){
console.log('setTimeout 0ms 3')
},0)
多次刷新,输出的顺序不太一致。因为while
的执行时间在1990
~ 2000
ms之间(谷歌速度快一丁点),并不是精确的2000
ms。而第一个延时输出的时间是在执行队列空闲2000ms后,相对精确一点。
为了搞清楚这几毫秒的差距,我还专门打印了不同内容输出所消耗的时间,大约在几毫秒至一百毫秒之间。
还可以看出一点,setTimeout
的时间控制也是在非主线程的,当while
循环执行时间超过2000
ms时,第一个延时(setTimeout 2000 ms)输出就稳稳的加入了队列的首位,while
循环执行时间小于2000
ms时,第一个延时就会排到第二输出的位置,第二个延时(setTimeout 0ms 2)来到了第一个位置。
至此,关于setTimeout
得出两点结论:
PS 还是有一点不明白,例如在3秒的while循环中输出new Date()
,只能输出有限多的内容,如果换作字符串+new Date()
,却可以输出上万条内容。WHY
由于字体不同,导致的line-height
差异,可以指定font-family
解决。比如右侧的+
新建文章显示效果。
相邻元素的排版出现的像素问题,一是因为元素换行后,产生的回车(文本元素),二是因为默认font-family
的不同,回车的宽度也不相同,导致不同浏览器计算像素的不一致。
今天打码的时候遇到一个有意思的现象,我本来是为了研究this
在对象中指向的情况:
var obj = {
self : this,
showThis:function(){
console.log('obj this from fn: ',this)
}
}
console.log('obj this: ',obj.self)
obj.showThis()
当然这两个显示一个是Window
,一个是{Object}
本身。
我在这个基础上,加上了setTimeout
:
var obj = {
self : this,
showThis:function(){
var this_ = this;
setTimeout(function(){
console.log(this_)
},10)
}
}
obj.showThis()
这时,setTimeout输出内容的仍是{Object}
。
但是,如果改一下:
var obj = {
self : this,
showThis:function(){
var this_ = this;
setTimeout('console.log(this_)',10)
}
}
obj.showThis()
控制台就会提示:this_ is not defined.
这是为什么呢?我又遇到了新的问题。
我于是尝试了以下两种不同的输出方式:
var obj = {
self : this,
showThis:function(){
var this_ = this;
setTimeout(function(){
eval('console.log(this_)')
},10)
}
}
obj.showThis()
//{Object}
var obj = {
self : this,
showThis:function(){
var this_ = this;
setTimeout(function(){
(new Function('console.log(this_)'))()
},10)
}
}
obj.showThis()
//Window
这说明,setTimeout
第一个参数是类似new Function
的执行,把执行作用域限定在了Global中。(Maybe?)
ls *.html -x -t | sed 's/[\t ]\+/,/g' | sed 's/.$/,/' | sed '$s/,/]/g'| sed '1 i\var list=[' > list.js
复习了以前一小段代码:
obj = {
toString(){
return 'obj '+super.toString()
}
}
我尝试用构造函数的形式写一个同样调用super
的方法。
先使用组合继承:
function Human(n){
this.name = n;
this.sayKind = function(){
console.log('i am a human')
}
}
function Man(n){
Human.call(this,n)
}
Man.prototype.toString = function(){
return 'my name is '+this.name+super.toString()
}
var jim = new Man('jim')
无论如何,super
只要出现,就会报错:Uncaught SyntaxError: 'super' keyword unexpected here。
改用ES6语法糖:
class Woman extends Human{
constructor(name,age){
super(name)
}
toString(){
return 'class string'+super.toString()
}
}
const mary = new Woman('mary')
在这里就可以使用super
了。
看来super
还需要同class
一起使用,至于obj
中的super
,权当是一种特例把。因为字面量是new Object()
的一种特殊形式,有明确的继承关系。
toString()
我试着在F12中直接执行toString()
,会显示[object Undefined]
,如果执行window.toString()
,则会得到`"[object Window]"。
10..toFixed(2)
//需要两个点,才能使整数变为小数
price.innerHTML
//这里的price获取不到,同name,id都无法获取到一样,可能是保留关键字?
//事实证明,price是我之前设定的变量名。脑子抽筋了
//while
var stopTime1 = new Date().valueOf() + 2000;
setTimeout(function() {
console.log('setTimeout include file')
}, 0)
console.log('include begin')
console.time('include job done')
while (new Date() < stopTime1) {}
console.timeEnd('include job done')
//promise
//这个貌似最精确
new Promise(function(resolve, reject) {
console.log('promise')
console.time('promise')
setTimeout(function() {
resolve()
}, 2000)
}).then(function() {
console.timeEnd('promise')
})
//async await
function sleep() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve();
}, 2000);
})
}
var start = async function() {
console.log('async')
console.time('async')
await sleep()
console.timeEnd('async')
}
start()
如果使用keypress
这个eventListener是不行的。
只能使用keydown
或keyup
:
document.addEventListener('keyup',function(e){
if(e.keyCode === 113 ){
//F2的起立键码
}
})
proxychains需要把dynamicChain的注释去掉,并且把strictChain注释掉.
proxychains使用ping命令无法访问www.google.com,但是使用telnet google.com 80可以看到返回.
本地代理如果检查配置正确,但是proxychains总提示timeout,需要重装代理.
做项目遇到数值排序,网上随便找了个函数
const compare = function(x,y){
if (x < y ) {
return 1;
} else if (x > y) {
return -1;
} else {
return 0;
}
}
arr.sort(compare)
因为数组的内容是php预先计算好的,通过js获取存入的是文本格式,结果出现了100以上的数反而比几十小的情况,研究了一下红宝书,在js里,比较大小的操作如果两个比较值都是文本,则直接比较ASCII的大小,并不会转换,所以这个找的函数只适用于数的比较,文本就不行。
改一下
const compare = function(x,y){
return x-y
}
这样就可以了,因为相减操作是先进行强制转换,对于文本的数就不会出现错误了。
好久不处理数字了,基础都忘了,要多复习基础知识。
TinyLog