HTML50 / tinyLog

a blog template based on Github issues comment
https://html50.github.io/tinyLog
2 stars 1 forks source link

tinyLog #1

Open HTML50 opened 7 years ago

HTML50 commented 7 years ago

TinyLog

HTML50 commented 7 years ago

ES6对象字面量新特性

前几天写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
};
HTML50 commented 7 years ago

严格模式下在函数内部声明函数又不报错了

今天在看严格模式(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()
4bt commented 7 years ago

行内元素与块级元素包含举例

看两个代码:

<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元素前会自动闭合。

延伸阅读:https://www.zhihu.com/question/34952563

4bt commented 7 years ago

history.scrollRestoration = 'manual'

今天逛论坛看见有人问:为什么注释的滚动执行不了

<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>标签内容都滚动出可视范围才会停止。

4bt commented 7 years ago

ES5中Array的几个新增方法小结

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

好了,就这几个。以后应该记得很清楚了。

4bt commented 7 years ago

this在setTimeout中指向的小细节

今天写代码时遇到个this的小问题。 大家都知道,在setTimeout,addEventListenerfunction中,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.usernameundefined

4bt commented 7 years ago

有意思

var a = {n:1};
var b = a;

a.x = a = {n:3}
console.log(a.x,a)
4bt commented 7 years ago

帮助理解setTimeout的小例子

var t = true;
window.setTimeout(function (){
    t = false;
},1000);
while (t){}
alert('end');
4bt commented 7 years ago

ID在HTML中唯一吗

<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中的唯一与否,在正确查询的基础上,基本没有使用上的影响。

4bt commented 7 years ago

正则表达式问题若干

今天写页面时遇到几个正则的问题。

1.flags值 es6之前是m g i三种,es6又添加了y u两种模式。 我在chrome v64上使用的是s模式(单行模式?),到v60就报错了。粗略研究了一下es8没找到s模式的内容,但估计已经得到了浏览器的支持。

2.匹配任意内容 /[\.\n]*/g[]内貌似\.是无效的,只能用[\s\S]*代替。

3.new RegExp() /\s*/gnew RegExp('\s*','g')是不一样的,使用new时需要双重转义:new RegExp('\\s*','g'),要有两个\

4bt commented 6 years ago

setTimeout参数为0时,内部函数与外部代码执行顺序探究

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 ~ 2000ms之间(谷歌速度快一丁点),并不是精确的2000ms。而第一个延时输出的时间是在执行队列空闲2000ms后,相对精确一点。 为了搞清楚这几毫秒的差距,我还专门打印了不同内容输出所消耗的时间,大约在几毫秒至一百毫秒之间。

还可以看出一点,setTimeout的时间控制也是在非主线程的,当while循环执行时间超过2000ms时,第一个延时(setTimeout 2000 ms)输出就稳稳的加入了队列的首位,while循环执行时间小于2000ms时,第一个延时就会排到第二输出的位置,第二个延时(setTimeout 0ms 2)来到了第一个位置。

至此,关于setTimeout得出两点结论:

  1. 延时执行与外部代码执行时间无关,只和任务队列顺序有关。
  2. 控制何时加入队列的时间计数器,在队列线程中,就算主线程阻塞了,也可以计算出阻塞了多长时间,是否要将延时任务加入队列。

PS 还是有一点不明白,例如在3秒的while循环中输出new Date(),只能输出有限多的内容,如果换作字符串+new Date(),却可以输出上万条内容。WHY

4bt commented 6 years ago

Chrome与FF等其他浏览器line-height差异

由于字体不同,导致的line-height差异,可以指定font-family解决。比如右侧的+新建文章显示效果。

相邻元素的排版出现的像素问题,一是因为元素换行后,产生的回车(文本元素),二是因为默认font-family的不同,回车的宽度也不相同,导致不同浏览器计算像素的不一致。

4bt commented 6 years ago

new Function()中的this

今天打码的时候遇到一个有意思的现象,我本来是为了研究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?)

4bt commented 6 years ago

遍历目录文件生成数组

ls *.html -x -t | sed 's/[\t ]\+/,/g' | sed 's/.$/,/' | sed '$s/,/]/g'| sed '1 i\var list=['  > list.js
4bt commented 6 years ago

super关键字

复习了以前一小段代码:

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]"。

4bt commented 6 years ago

小知识

 10..toFixed(2)
//需要两个点,才能使整数变为小数

price.innerHTML
//这里的price获取不到,同name,id都无法获取到一样,可能是保留关键字?
//事实证明,price是我之前设定的变量名。脑子抽筋了
4bt commented 6 years ago

等待2秒的三种写法


//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()
4bt commented 6 years ago

监听F1-F12等功能键的方法

如果使用keypress这个eventListener是不行的。 只能使用keydownkeyup

document.addEventListener('keyup',function(e){
   if(e.keyCode === 113 ){
      //F2的起立键码
   }
})
4bt commented 6 years ago

ProxyChains/lubuntu下命令行使用代理

proxychains需要把dynamicChain的注释去掉,并且把strictChain注释掉.

proxychains使用ping命令无法访问www.google.com,但是使用telnet google.com 80可以看到返回.

本地代理如果检查配置正确,但是proxychains总提示timeout,需要重装代理.

HTML50 commented 4 years ago

js的sort排序

做项目遇到数值排序,网上随便找了个函数

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
}

这样就可以了,因为相减操作是先进行强制转换,对于文本的数就不会出现错误了。

好久不处理数字了,基础都忘了,要多复习基础知识。