blog's People
blog's Issues
Javascript中css选择器的陷阱
之前写了一大段都删了,想了想没必要介绍api的使用。querySelector querySelectorAll这两个api现在应该没人不知道
这里只简单说下使用时容易遇到的两个坑
document.querySelectorAll返回的是静态的nodelist,可以理解为某一时间的快照
举个例子说就是如果一个ul下有两个li,现在我用querySelectorAll获取li,如果以后再动态的添加几个li,querySelectorAll返回的nodelist是不会包括后来动态添加的li的,而getElementByTagName获取到的nodelist则是动态的,就算后来动态添加的元素一样可以获取到
<ul>
<Li>a</li>
<li>b</li>
</ul>
另外一点是返回的结果可能与预想中的有偏差 id为test的元素中没有div元素,但是返回的并不是空数组,可以自行实验一下
<div id="test">
<b>Hello</b> I'am a ninja
</div>
var a = document.getElementById('test').querySelectorAll('div b');
console.log(a);
下面是JQ的作者给出的一个方法,使其正确的匹配,首先必须为元素赋予元素一个唯一的id,并且稍后将原始的id恢复回去,然后将id 拼接在选择器前面
(function() {
var count = 1;
this.rootedQuerySelectorAll = function(elem, query) {
var oldId = elem.id;
try {
return elem.querySelectorAll('#' + elem.id + " " + query);
}
catch(e) {
throw e;
}
finally {
elem.id = oldId;
}
}
}) ()
var b = rootedQuerySelectorAll(
document.getElementById('test'),
'div b'
)
console.log(b);
听着歌吹着晚静静的瞧着代码
每当夜幕降临的时候,一个人静静的听着歌,开着窗户,晚风略带凉意的拂过,找个惬意的角度坐在椅子上敲着代码。
只有这时候写的代码才有归属感,思维也最为活跃。摆脱了白天重复的业务,摆脱了各种脑残产品经理,
这时候的代码才有了生命
这几天在仿写简易版的vue,不准备发博客具体说什么了,因为网上XXX源码分析太泛滥了,再去说什么总有炒冷饭的嫌疑,我也不喜欢炒冷饭。
其实仿写个简易库或者框架真的不难,前人已经总结很多经验了,找几篇博客看看在动手写几遍很轻松就可以学会的,令我诧异的是很多公司面试问你源码以便于考验基础扎实与否,其实这东西跟基础扎实没什么关系啊,只要看了遍高程+ 工作一段时间,想要简单的了解源码实现真的很轻松的
还有不少面试官觉得懂源码业务就能写好,其实完全是两个不同的方向
造螺丝刀的一定用得好螺丝刀吗? 关键是你想钻研哪个方向
想起以前领导的一句话,嵌入式、安全、应用领域、各种业务场景都鼓捣过,但是我知道我最擅长的是架构,以后分工一定越来越细,想好自己想要做什么。
浏览器中的标签切换事件
其实没什么好写的,逛知乎的时候突然断网了,于是我切换回小说标签页继续看没看完的小说,小说看得差不多了切回知乎的时候弹出一个错误提示,请原谅我的无聊,我来回切换十多次每次都弹出一个错误提示。我突然想知道这是怎么实现的,在google上搜索一番
相关资料
浏览器提供了visibilitychange这个api可以监控标签页的状态
应用场景大概想了一下视频直播 h5游戏可能用得上
写了一个demo,随便看看就好了
代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>switch1</title>
</head>
<body>
<script>
function add0(m){return m<10?'0'+m:m }
function getDate() {
var time = new Date()
var y = time.getFullYear();
var m = time.getMonth()+1;
var d = time.getDate();
var h = time.getHours();
var mm = time.getMinutes();
var s = time.getSeconds();
return y+'-'+add0(m)+'-'+add0(d)+' '+add0(h)+':'+add0(mm)+':'+add0(s);
}
function onVisibilityChanged(event) {
var hidden = event.target.webkitHidden;
if (hidden) {
console.log('close',getDate())
}
else{
console.log('open',getDate())
}
}
document.addEventListener("webkitvisibilitychange", onVisibilityChanged, false);
</script>
</body>
</html>
apply的用处
先谈this
关于this的指向就不细说了,网上有无数博客以及you don't kown js这类书讲的已经很详细了这里就不炒冷饭了。
举几个简单的例子
function foo() {
console.log(this);
}
foo() //window
var obj = {
job: 'doctor',
show: function() {
console.log(this.job); //job
console.log(this === obj); //true
}
}
obj.show();
apply的用途
改造一下上面的例子
var obj = {
job: 'doctor',
}
function foo(str) {
console.log(this); //obj
console.log(str); //hi
}
foo.apply(obj,['hi']);
调用一个函数的方法有很多可以用函数表达式调用,也可以直接调用。还有一种方法是用apply调用
apply接受两个参数,第一个参数是函数运行时指向的this,第二个参数是一个数组里面存放函数的参数。
也就是我们可以手动更改this的指向,再次看上面的代码我们让函数foo中的this指向了obj,还接受了一个字符串'hi'
那么反过来我们是否可以在foo中对obj的属性进行赋值呢?答案是肯定的
再次更改代码
var obj = {
job: 'doctor',
}
function foo(str) {
this.books = ['One Hundred Years of Solitude', 'Gone with the wind']
}
foo.apply(obj,['hi']);
console.log(obj); // {job: "doctor", books: Array(2)}
apply的用处无所不在,比如将nodelist转为数组,类型检测这些网上同样有很多例子
apply与函数式编程
如果我们有声明一个数组并想得到数组中每一个元素的值我们可以这么做
var arr = ['katana', 'chunks', 'shurken'];
for(var i = 0;i<arr.length; i++) { //直接在循环写arr.length并不是一个好习惯
console.log(arr[i])
}
但是这种声明式的写法是不是有些丑陋?让我们换一种写法
function forEach(list, callback) {
for(var n = 0; n<list.length; n++) {
callback.call(list[n], n, list[n]);
}
}
var arr = ['katana', 'chunks', 'shurken'];
forEach(arr, function(index, value) {
console.log(index);
console.log(value)
})
正则表达式之小有名气
在上一篇文章已经讲了如何匹配简单的字符串,如何全局搜索,以及一些特殊字母i,g,m所代表的含义
这篇文章讲的内容有点多最好分两次读,不过不用担心很多东西并不需要你特意记住
知道有那么一回事先用先查都OK
再谈^和$
之前已经了解过[^abc]表示除a,b,c之外的字符,现在又要多一种用法了
/^test/ 表示以test开头的字符 这里的^表示以...开头
那么$表示什么呢? 它的含义是以...结尾
/test$/ 表示以test结尾的字符
转义
首先我们要知道并不是所有的字符都与自身等价的,比如/hello/表示我们要匹配‘hello’字符,但是如果想匹配food$并不能这么写/food$/,因为$有独特的含义,就像我们上篇文章学到的[],^这几个符号一样。如果想要匹配'food$'这个字符串,那就需要用反斜杠进行转义,通俗的说就是在特殊符号前面加上\ 就像这样
/food\$/ 匹配food$字符
从webpack配置学正则
我copy了一段webpack配置,只看rules中test表示的正则就可以
在正则中.也有特定的含义,所以如果把它当字符进行匹配的话也要进行转义根据上面所学到的,判断下面代码中的正则表达式所代表的含义,答案我已经写在注释中了
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },//以.css结尾的 使用css-loader处理
{ test: /\.ts$/, use: 'ts-loader' }// 以.ts结尾的
]
}
};
重复匹配
如果要匹配四个‘a’字符,我们当然可以用/aaaa/这样表示,如果匹配5个'a' 10个'a'呢?正则没那么‘傻’早已为我们准备了简便方法/a{4}/ 表示匹配含有连续4个'a'的字符
在重复选项上,正则提供了很多方式
- 在一个字符后面加一个'?',可以定义该字符是可选的(可以出现一次或者根本不出现)
/t?est/ 可以匹配 test 或者 est
- 如果一个字符要出现一次或多次(至少出现一次),可以使用加号'+'
/t+est/ 可以匹配test ttest tttest 而不能匹配est
- 如果一个字符要出现零次或多次,可以使用星号'*' (注意与?的区别,?代表要么不出现要么只能出现一次 *代表要么不出现要么出现不止一次)
/t*est/ 可以匹配test ttest tttest est
- 也可以在字符后面的花括号里指定一个数字来表示重复次数
/a{4}/ 匹配包含连续4个a的字符串
- 也可以在字符后面的花括号指定一个重复次数的区间
/a{4,10}/ 匹配任何含有连续4个至10个a的字符串
- 还可以在省略区间中第二个值(但是要保留逗号) 这里直接上代码,用文字叙述容易迷糊
/a{4,}/ 如果逗号后面不写第二个参数那么表示匹配任何含有连续4个或多于4个a的字符串
这些重复操作符可以是贪婪的可以是非贪婪的,默认情况它们是贪婪的
这里不用口语叙述,看代码更直观
遇到连续四个a即停止搜索
var str = "aaaabbbcaadda"
var newStr = str.replace(/a+/,'嘿')//"嘿bbbcaadda"
因为加了g进行全局匹配,我们看一看有哪些字符符合条件
开头的4个a
c后面的2个a
d后面的a
这就是贪婪匹配遇到成串的符合条件的字符,将匹配这个’串‘
var str = "aaaabbbcaadda"
var newStr = str.replace(/a+/g,'嘿')//"嘿bbbc嘿dd嘿"
如果后面在'+'后跟了'?'则表示进行非贪婪匹配,具体结果请看注释
var str = "aaaabbbcaadda"
var newStr = str.replace(/a+?/g,'嘿')//"嘿嘿嘿嘿bbbc嘿嘿dd嘿"
分组
上面已经说到可以用/t+est/这种用法,但是+只影响它前面的t,如果想让+影响多个字符可以使用括号进行分组
/(ab)+/ 匹配一个或多个连续出现的字符串'ab'
var str = "abcdababef"
var newStr = str.replace(/(ab)+/g,"嘿")//"嘿cd嘿ef"
请注意cd后的连续两个ab被替换成一个嘿而不是两个
'|'操作符
可以使用竖线表示或者
/a|b/ 匹配a或b字符
/(ab)+|(cd)+/ 匹配出现一次或多次的“ab” 或者“cd”
这一篇概念有点多,不需要一下看完,分两次看好了。本来想把一些预定义字符类写完的,转念一想灌输太多内容是不利于学习的,而且那些东西也并不是很重要,只是用的时候现查的一些字母而已。所以留到下章再说
一些代码简化技巧
今天看到的一段代码如下,可以省略if
lis[cidx].style.webkitTransition = '-webkit-transform 0.2s ease-out';
lis[cidx-1] && (lis[cidx-1].style.webkitTransition = '-webkit-transform 0.2s ease-out');
lis[cidx+1] && (lis[cidx+1].style.webkitTransition = '-webkit-transform 0.2s ease-out');
购物车页面通常有这样一个功能,有个input表示当前所选商品数量左右各一个按钮表示+ - 当前数量
通常所选商品数量不能为负可以用以下代码省略if
Math.max(num,0)
简单了解node.js调试方法
调试能力是编程的基本素质之一,快速的定位bug可以让开发者到点下班,免于加班之苦。众所周知JavaScript调试是非常方便的,只要打开浏览器按下F12,console.log也好打断点也好,总是可以轻易的定位到错误。甚至很多错误一看控制台报的错误信息瞬间就明了。那么node.js如何进行调试呢?
使用chrome插件NIM
参考官网的debug方法,首先安装chrome插件NIM(需要科学上网)然后执行需要调试的文件,比如有个test.js文件那么在终端输入node --inspect-brk test.js 然后chrome会自动新建一个页面供你调试下面是图文步骤
随便写点什么东西
安装在chrome应用商店安装NIM(如果访问不了,可以搜索谷歌访问助手进行科学上网)
安装完成之后直接运行node.js文件
浏览器会自动打开一个页面用于调试,断点调试方法不再叙述
而且在这里可以看出为什么在node.js中每个文件都是单独的一个模块,每个文件的代码都被包在了一个函数中。也可以观察函数调用栈更深入的研究node.js
vscode调试
vscode是一款微软出的编辑器,它自带调试功能。没用过的下载安装,用过的直接打开vscode
点击红圈中的图标
会打开一个json配置文件在configurations中的对象里追加一行配置
"configurations": [
{
// here is somecode
"cwd": "${cwd}"
}
]
ctrl+s保存
在代码当前行的左侧就可以直接打断点,然后点击编辑器左上方的三角绿色按钮开始调试。并且可以像chrome那样step into step out进行断点调试
说到这里就差不多了,还有很多方法可以调试比如直接在代码中dubugger,后续有时间会继续更新的
如何用JavaScript判断dom是否有class的值?
闲逛segmentfault的时候看到有个问题,如何判断dom中存在某个class.我稍微想了想可以用classList来进行判断
<div class="demo"></div>
let classList = document.querySelector('.demo').classList;//['demo']
let hasClassName = classlist.indexOf('demo')===-1?false:true
正则表达式之初入江湖
为什么要学正则表达式
很多人对正则表达式的认知只是在进行表单验证的时候在网上搜一段正则表达式进行copy,实际工作上好像很难遇到大段的正则表达式
我第一次看到大量的正则使用是在jQuery源码中,当时看的头疼只好草草的看下大概思路不了了之,但是到今天我依然不认为这种做法是错误的,jQuery早期为了兼容性代码很多地方太脏,不如在网上搜搜源码架构。拿jQuery举例子只想说明你总会在一些阴暗的角落遇到正则表达式,为了到时候不至于一头雾水,我们最好简单的了解一下正则表达式的使用。
看完本文你不会称为正则专家,实际你也不需要精通正则,能看懂别人写的正则和能写一些简单的正则即可
之前在网上搜过一些文章,感觉写的都不太好把我的耐心都磨没了所以我决定写一篇符合“人”学习直觉的文章
创建正则表达式
在JavaScript中与大多数其他对象类型一样,有两种方法可以创建正则表达式比如我们要匹配一个"test"字符串
- 通过正则表达式字面量
var pattern = /test/;
- 通过构造RegExp实例
var pattern = new RegExt("test");
前者直接在//中写匹配规则就Ok了,后者需要调用RegExt构造方法,并把匹配规则用""包起来,很明显第一种更加清晰,反正我每次都记不住"RegExt",每次用都要现查,所以我们接下来用第一种就好了(RegExt有它的好处但是目前不需要知道)
现在你一定想知道/test/表达的是什么意思?
这种一个接一个的字符,隐式的表达了"followed by"这样一个操作也就是一个挨着一个
- 't'后面跟着'e'
- 'e'后面跟着's'
- 's'后面跟着't'
正则表达式的威力仅此而已吗?如果只是这样就太让人失望了,因为完全可以使用indexOf进行判断
接下来我们额外学习三个英文字母,在正则中他们有各自的含义
- i 让正则表达式不分大小写 /test/i 表示不仅可以匹配'test'还可以匹配'TeSt'
- g 全局匹配 默认情况正则只匹配第一次出现的结果比如'testkdgyitest' 找到第一个'test'就算完成工作了,而g可以找到所有符合条件的匹配值
- m 允许匹配多个行比如匹配textarea中的值
请记住这些字母跟在//后面 如/test/i
接下来让我们做个小练习,有如下字符串,将字符串中的test(不区分大小学)替换成“啊哈正则” 提示:js替换字符串常用replace方法并且replace第一个参数接收正则表达式
var str = "sjufhsufhTesT";//将test(不论大小写)替换成“啊哈正则”
答案:
var str = "sjufhsufhTesT";
var pattern = /test/i;
var newStr = str.replace(pattern, "啊哈正则");
前面说了默认情况正则只匹配第一次出现的结果,我们来测试一下
var str = "testsjufhsufhTesT";
var pattern = /test/i;
var newStr = str.replace(pattern, "啊哈正则");// 结果如下"啊哈正则sjufhsufhTesT"
我们加上g试试
var str = "testsjufhsufhTesT";
var pattern = /test/ig;
var newStr = str.replace(pattern, "啊哈正则");// 结果如下"啊哈正则sjufhsufh啊哈正则"
匹配一类字符
有时候我们想更灵活一些,不想只匹配某个特定的字符串,而是想匹配集合中的某一个字符,比如我们只想匹配“a” “b” “c”中任何一个字符 我们可以这么写[abc]
[]中可以指定一个集合比如[abc],那么如果想指定一个从a到z的集合,难道我们把26个英文字母一个一个写一遍吗?当然不需要!我们可以在[]中指定范围[a-z]
没懂?看下面的例子就好了
var str1 = "ak恩ebc";
var pattern1 = /[abc]/;
var newStr1 = str1.replace(pattern1,"雅儿");
console.log(newStr1);//雅儿k恩ebc
我们看到我们想要abc之中的任何一个字符,即使中间隔着其他字符也没关系,但是默认情况是如果找到了a就停止往下继续匹配b和c了,如果没匹配到a,那么将匹配b,以此类推
如果想全部匹配请加上在//后加上"g"
现在有个新需求,匹配除abc之外的字符,我们怎么办呢?可以在集合中插入一个"^" [^abc]
"^" 表示除...之外
var str2 = "ak恩ebc";
var pattern2 = /[^abc]/g;
var newStr2 = str2.replace(pattern2,"雅儿")
console.log(newStr2);//a雅儿雅儿雅儿bc
各位看客看到这里想必也累了,余下的内容以后再说。先把这次的内容复习一下
- 正则表达式的两种创建方式
- i g m 三个字母代表的特殊含义 i表示不区分大小写 g表示全局匹配 m表示允许匹配多个行 (别忘了写在//后 如/test/i)
- 可以用[]匹配集合中的某个字符串
- 可以^实现反选,表示除...之外
最后推荐一个正则可视化工具,可以在上面练习正则,通过可视化的方式更轻松的理解
File
选择文件
通过input type="file" 浏览会创建一个提供选择文件功能的按钮。选中文件后会创建一个file对象有如下信息(只读)
- name:本地文件系统中的文件名
- size:文件的字节大小
- type:字符串,文件的MIME类型
- lastModifiedDate:字符串,文件上一次被修改的时间
每次创建的file对象会存储在一个叫files的数组中
<input type="file" id="file"/>
FileReader
你可能会想可不可以读取选中文件的内容,当然是可以的。浏览器提供了FileReader这个构造函数。不需要理解它,记住以下套路就可以了
- var reader = new FileReader(); 这是套路不需要理解
- FileReader提供了几种读取文件的方法如下:
- reader.readAsText(file, 'utf-8');一般用来读取文本默认编码为utf-8
- reader.readAsDataURL(file);:说白了将文件生成一个本地uri,而且是以base64编码的形式体现
- reader.readAsBinaryString(file);读取文件的二进制流
- reader.readAsArrayBuffer(file);读取文件的array buffer
//html部分
<input type="file" name="file" id="file"/>
//script部分
//给input type="file"绑定change事件
var file_el = document.getElementById('file')
file_el.onchange = function() {
取出file对象
var file = file_el.files[0]
记住这是套路
var reader = new FileReader();
比如我们读取一个txt文本文件
reader.readAsText(file, 'utf-8');
当读取操作成功完成时调用
reader.onload = function(e){
其实本质上说无论是readAsText还是readAsDataURL以及其他方法
影响的是reader.result返回结果不同,大家可以挨个试试
console.log(reader.result)
}
}
预览图片
预览图片有两种方法,通过input type="file" 拿到files[0]之后创建一个img标签
1 通过window.URL.createObjectURL(file);创建一个文件的临时路径,将生成的url赋值给img
2 通过file.reader拿到返回的result 将result赋值给img的src
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.