cruxf / studyjavascript Goto Github PK
View Code? Open in Web Editor NEW这是一个通过实现各种功能来学习JavaScript的小仓库
这是一个通过实现各种功能来学习JavaScript的小仓库
这是最近看的一套妙味课堂的学习视频,内容算是精品,概念结合demo,再加上每次的练习,能够感受的到,实打实完成这套视频中所有任务,能完成平时工作大部分的业务开发以及对JavaScript一些基础概念的理解。下面进入正题
如果我们希望把某个元素移出视线中,那么有以下的方法
在JavaScript中通过id名称获取元素:docuemnt.getElementById('id'); 其中鼠标事件有以下几种
函数调用的三种方式
下面我们来看一个鼠标移入和移出事件的demo演示以及源码(mouseEvent.html)
我是演示
我是源码
其实对于以上的源码我们还能做些改进,比如将获取元素id的冗长代码进行封装,使代码变得简洁
// 封装
function getDom(id) {
return document.getElementById(id)
}
// 调用
var li = getDom("lis")
var ul = getDom("ul1")
以上代码是我们放在body元素底部才得以实现,假如放在body元素的前面会发生什么事情呢?首先,因为js代码的解析依赖的是js引擎,该引擎是个单线程,所以会阻塞body中DOM的渲染;然后,如果js代码中有操作DOM的行为,那么会报错,因为此时DOM还尚未被渲染出来。
假如执意要把js代码放在body前,那么只要将代码放在 window.onload = function(){ 代码执行区 } 即可。下面我们来看看到底什么时候采取匿名式的函数调用?什么时候采取元素.事件 = 函数名的调用方式?
我是演示
我是源码
当然,我们也能够对上述代码进行优化,比如封装获取元素id的方法以及抽离元素的style冗余设置,详情请看优化版的demo。
以上的处理虽然使代码量变得很少,但是通用性是完全不够的,具体源码请查看day01目录下的test.js文件,知道怎么优化的小伙伴请留言哈。
JavaScript能够获取元素中的属性值,比如获取表单元素中的value值
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script>
window.onload = function() {
var oBtn = document.getElementById("btn1")
var oText = document.getElementById("text1")
var oSelect = document.getElementById("select1")
oBtn.onclick = function() {
alert(oText.value + " 在 " + oSelect.value)
}
}
</script>
</head>
<body>
<input id="text1" type="text" />
<select id="select1">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="杭州">杭州</option>
</select>
<input id="btn1" type="button" value="按钮" />
</body>
</html>
根据上面的代码,其实我们也能够修改元素的属性值,比如下面的代码
window.onload = function () {
var oBtn = document.getElementById('btn1');
var oText = document.getElementById('text1');
var oSelect = document.getElementById('select1');
oBtn.onclick = function () {
oText.value = oSelect.value;
};
};
于此我们能够做的操作非常多,比如查找到一个img元素,能通过表单输入控制src属性的值,实现手动修改图片地址。
和表单的value相对应的是其他一些元素的innerHTML属性
window.onload = function () {
var oBtn = document.getElementById('btn1');
var oText = document.getElementById('text1');
var oP = document.getElementById('p1');
oBtn.onclick = function () {
oP.innerHTML = oText.value;
};
};
对元素属性的操作我们能玩的东西实在是太多了,比如
对以上功能实现感兴趣并且还不是熟悉的,可以自己先试着实现一遍,再去看源码。下面我们来看今天的作业,首先是第一个作业
和“切换图片的综合案例”可以说是一样的,不过我们可以按着自己的想法重新写一遍js代码,我在其中做的一些改变是:
最后的实现虽然与效果有些UI上的差异,不过大体上算是符合功能需求,实现了一个简陋的动态聊天页面,下面请看效果
效果演示
获取元素的方法
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script>
window.onload = function() {
var oUl = document.getElementsByTagName("ul")[0];
var aLi = oUl.getElementsByTagName("li");
for (var i = 0; i < aLi.length; i++) {
aLi[i].style.color = "red";
}
};
</script>
</head>
<body>
<ul>
<li>无序列表1</li>
<li>无序列表2</li>
<li>无序列表3</li>
</ul>
<ol>
<li>有序列表1</li>
<li>有序列表2</li>
</ol>
</body>
</html>
for循环,在工作中需要特别注意下性能上的问题,可以执行下面两段代码,能够凭借肉眼看出渲染性能上出现巨大的差别
// 性能巨差的for操作
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += '<input type="button" value="按钮" />';
}
// 性能较佳的for操作
var str = '';
for (var i = 0; i < 1000; i++) {
str += '<input type="button" value="按钮" />';
}
document.body.innerHTML = str;
对于for循环,我们还可以做一些元素位置的操作,效果请点击这里,接下来又两个小练习
for循环的常用场景还有嵌套这一块,简单的demo效果请点击这里
利用JavaScript设置元素的样式,除了可以添加一个类名(className)、单独设置某个样式(elment.style.params),我们还可以使用cssText直接添加所有的样式,和添加类名类似
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style>
div {
width: 100px;
height: 100px;
border: 1px solid #333;
}
</style>
</head>
<body>
<div id="div1">123</div>
<input id="btn1" type="button" value="按钮" />
<script>
var oDiv = document.getElementById("div1");
var oBtn = document.getElementById("btn1");
oDiv.onclick = function() {
oDiv.style.cssText = " width:200px; height:200px; ";
};
oBtn.onclick = function() {
oDiv.style.cssText = "";
};
</script>
</body>
</html>
对于this的理解,一直是JavaScript的一座山,当你对它理解通透的时候,那么就能写出逼格很高的代码,简单来说,this指的就是调用当前方法(函数)的那个对象,下面我们先看一段简单的代码,以此对this有个初步的了解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>this基础</title>
</head>
<body>
<button>按钮一</button>
<button onclick="fn()">按钮二(this指向window)</button>
<script>
let btn = document.getElementsByTagName("button");
btn[0].onclick = function() {
fn(); // this指向window
};
btn[0].onclick = fn; // this指向btn[0]
function fn() {
console.log(this);
}
fn(); // this指向window
</script>
</body>
</html>
下面开始今天练习小demo,首先看第一个:要求必须解决所有浏览器兼容性问题
对于这个练习,我只做了个大概的功能演示,本来是想用事件代理来实现,结果脑子不太好使,只能使用for循环来写,点击这里看效果
第二个:自动生成10个li,只能用定位实现(基础版)
挺简单的一个练习,没啥好讲的,使用for循环同时取余判断即可,点击这里看效果
第三个:自动生成100个li,只能用定位实现(提高版)
跟上一个练习类似,除了使用for循环和取余,我们还需要个额外变量用作换行处理,具体点击这里看效果
第四个:自动生成V字型-只能用定位实现(基础版)
之前有写过,思路挺简单的,就是找到中心点,然后以中心点的位置做一些操作,具体点击这里看效果
第五个:自动生成V字型-只能用定位实现(提高版)
能够动态变化的V字型,思路也是和第四个练习一样,难就难在如何封装一个高复用性的函数/方法,在这一点上我是没啥好思路,用了最笨拙的方式写出来了,具体点击这里看效果
js的数据类型有种划分方式为原始数据类型和引用数据类型。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<script>
// 原始数据类型
let num = 33
let unde = undefined
let nul = null
let bo = true
let str = 'yy'
let sym = Symbol('4jht')
console.log(typeof num) //number
console.log(typeof unde) //undefined
console.log(typeof nul) //object
console.log(typeof bo) //boolean
console.log(typeof str) //string
console.log(typeof sym) //symbol
console.log(Object.prototype.toString.apply(num)) //[object Number]
console.log(Object.prototype.toString.apply(sym)) //[object Symbl]
// 引用数据类型
function fn(){}
let obj = {}
let arr = []
console.log(typeof fn) //function
console.log(typeof obj) //object
console.log(typeof arr) //object
console.log(fn instanceof Function) //true
console.log(fn instanceof Object) //true
console.log(obj instanceof Object) //true
console.log(arr instanceof Array) //true
console.log(arr instanceof Object) //true
console.log(Object.prototype.toString.apply(fn)) //[object Function]
console.log(Object.prototype.toString.apply(arr)) //[object Array]
</script>
</body>
</html>
对于数据类型检测,我们通常有下面几种方法
关于数据类型,还有数据的隐式转换和显式转换
下面进入今天的作业环节,首先看第一道题
var arr = ['100px', 'abc' - 6, [], -98765, 34, -2, 0, '300', , function () {alert(1);}, null, document, [], true, '200px' - 30, '23.45元', 5, Number('abc'), function () {alert(3);}, 'xyz' - 90];
/*
1、找到arr里所有的数字:-98765, 34, -2, 0, 5
2、找到可以转成数字的:'100px', -98765, 34, -2, 0, '300', '23.45元', 5
3、把转成数字以后,最大值判断出来:300
4、把 NaN 所在的位置找出来:1 14 17 19
*/
实现并不难,只是有些细节需要留意下,比如NaN和typeof也是为number。最终我用一种比较笨的方法实现了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
var arr = ['100px', 'abc' - 6, [], -98765, 34, -2, 0, '300', , function () {alert(1);}, null, document, [], true, '200px' - 30, '23.45元', 5, Number('abc'), function () {alert(3);}, 'xyz' - 90];
var num = [] //1
var arrStr = [] //2
var allNum = []
var maxNum = 0 //3
var nanPo = [] //4
arr.forEach((item,index)=>{
if(!isNaN(item) && typeof item == 'number'){
num.push(item)
}
if(!isNaN(parseFloat(item)) && typeof parseFloat(item) == 'number') {
arrStr.push(item)
allNum.push(parseFloat(item))
}
if((''+item)=='NaN') {
nanPo.push(index)
}
})
console.log(num) //[-98765, 34, -2, 0, 5]
console.log(arrStr) //['100px', -98765, 34, -2, 0, '300', '23.45元', 5]
console.log(Math.max.apply(null, allNum)) //300
console.log(nanPo) //[1, 14, 17, 19]
</script>
</body>
</html>
第二题是判断输入的内容是否符合规则,比较简单,我直接贴代码了
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<body>
请输入QQ号码:<input type="text" />
<input type="button" value="判断" />
<br />
1、有没有输入<br />
2、输入的是不是数字<br />
3、不能有0在前面<br />
4、不能是小数<br />
5、输入的数字必须在5位以上、10位以内
<script>
let input = document.getElementsByTagName("input");
let btn = input[1];
btn.onclick = function() {
if (input[0].value == "") {
alert("请输入内容");
input[0].value = "";
input[0].focus();
} else if (isNaN(input[0].value)) {
alert("请输入数字");
input[0].value = "";
input[0].focus();
} else if (input[0].value.charAt("0") == 0) {
alert("不能有0在前面");
input[0].value = "";
input[0].focus();
} else if (input[0].value.indexOf(".") != -1) {
alert("不能输入小数");
input[0].value = "";
input[0].focus();
} else if (input[0].value.length < 5 || input[0].value.length > 10) {
alert("输入的数字长度应该大于5且小于10");
input[0].value = "";
input[0].focus();
} else {
alert("输入数字符合规则");
}
};
</script>
</body>
</html>
为了提高代码的复用性,降低平时重复的搬砖,因此我们需要时刻留心将项目中能够在多处进行复用的代码封装起来,通过传入的参数来决定一些特定的行为。下面我们先看一个图片浏览的案例效果
点击这里查看效果
为了加深下印象,我们再来看看一个类似于计算商品的demo,点击这里查看效果
这个作业看似简单,然而坑依然是有的,比如父元素中子元素对其事件的影响,这点着实让我感到十分头疼,最终依然还是在网上找到了解决的办法,可以点击这里查看坑的点。虽然最后实现的并不是百分百还原,但是功能还是基本实现了,点击这里查看效果
实现了功能,然而代码质量却十分一般,有点心累,不过还是得坚持下去,发现自己的不足,锻炼自己的能力,弥补自己的不足,点击这里查看效果
《JavaScript高级程序设计》是一直被推崇的前端开发经典书目,在网上也被成为“红宝书”或“红皮书”。而我在断断续续中把这本书过了一遍,然而却发现好像根本就学到多少!从那时我就开始想问题到底出现在哪,后来才发现其中存在的两个问题:1、妄图记住书中的全部信息,搞得自己身心俱疲;2、不加思考的摘抄和记录,稍过几天,马上忘得一干二净。
根据发现的问题,重新用一种偷懒的方式来整理一遍这本书的知识点,同时还关注了《喜马拉雅》同款说书节目,希望能带来一丝好效果,让自己成为一个更加专业的前端工程师,Let's Go!^_^
要想全面理解和掌握JavaScript,关键在于弄清楚它的本质、历史和局限性。
一个完整的JavaScript实现应该由以下三部分组成:
概念
文档对象模型是针对XML但经过扩展用于HTML的应用程序编程接口。DOM把整个页面映射为一个多层节点结构,HTML或XML页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。根据我的理解DOM就是:浏览器渲染HTML后出现的一种结构。
作用
通过DOM创建的这个表示文档的树形图,开发人员获得了控制页面内容和结构的主动权。借助DOM提供的API,开发人员可以轻松自如地删除、添加、替换或修改任何节点。
DOM级别
开发人员使用BOM可以控制浏览器显示的页面以外的部分,从根本上讲,BOM只处理浏览器窗口和框架,但人们习惯上也把所有针对浏览器的JavaScript扩展算作BOM的一部分,下面就是一些这样的扩展
在如今移动互联网当道,以及Vue、React和Angular横行的时代,这个章节中的内容变得并不是那么的重要,下面简单说一下稍微要留意的三个点。
在script元素中设置defer属性,相当于告诉浏览器立即下载,但是延迟执行。意思就是表明脚本在执行时不会影响页面的构造。
在script元素中设置async属性,目的是不让页面等待脚本下载和执行,从而异步加载页面其他内容。
1、同步调用时一种阻塞式调用,一段代码调用另一段代码时,必须等待这段代码执行结束并返回结果后,代码才能继续执行下去。例如下面的代码
let n1 = 1
let n2 = 2
let n3 = 3
alert(n1)
alert(n2)
alert(n3)
// 运行结果: 1 2 3
2、异步调用是一种非阻塞式调用,一段异步代码还未执行完,可以继续执行下一段代码逻辑,当其他同步代码执行完之后,通过回调返回继续执行相应的逻辑,而不耽误其他代码的执行。例如下面的代码
let n1 = 1
let n2 = 2
let n3 = 3
alert(n1)
setTimeout(function() {
alert(n2)
}, 2000)
alert(n3)
// 运行结果:1 3 2
当然,关于异步还有另外一个例子,这个栗子也引出了异步调用和回调这两个东东的概念,下面请看代码
function Person() {
this.think = function(callback) {
setTimeout(function() {
console.log('想出来了!')
callback()
}, 5000)
}
this.answer = function() {
console.log('我正在思考一个问题^_^')
}
}
var person = new Person()
person.think(function() {
console.log('花费5s,得到一个正确的思考')
})
person.answer()
// 我正在思考一个问题^_^
// 想出来了!
// 花费5s,得到一个正确的思考
这章的内容表面看挺浅显的,但是一旦要深挖的话却是能挖掘出很多充满奥妙的东西,例如两个值在比较过程中所发生的类型转换,有兴趣的可以来看看这篇文章
也是从该章的内容才意识到:《JavaScript高级程序设计》这本书其实本质上是一本非常好的工具书,在JavaScript这块遇到不太明白的问题,拿出翻一番就好,要是想要一点不漏的把书中全部的知识在段时间内吸收的话,那简直是不可能的事情,因此接下来的笔记我不会像记录流水账一样把书中大部分内容摘抄下来,而是选择一些有代表性的东西说一说,同时也将网上一些比较好的解读分享出来
这一章对我而言,说简单也算是简单,也难也有难的一方面。简单的是对变量以及作用域的理解,难的是内存那一块看得十分的懵逼,接着就上网翻了一番,发现以下几篇认为比较好的文章,自己比较认同,所以我就不做重复的总结工作了,看看别人的就行,留点时间与精力去做更多的事情
1、javascript中创建变量时作用域和内存详解!
2、JavaScript--变量、作用域及内存
3、JavaScript 内存泄漏教程
篇幅十分长的一章,里面涉及到的也是一些重要且基础的知识,有好多学习者们都对这章进行了总结与摘抄,我就不做重复劳动了,下面请看一些总结
1、JavaScript引用类型
2、JavaScript之引用类型
毫无疑问,这章节是一道坎,一道区分自身是初级程序员还是高级程序员的坎。这个章节的知识太重要了,唯一不足的地方是要掌握这章的知识实在是有难度,我们需要多维度的去学习该章节,比如其他人的总结:
javascript面向对象程序设计系列(一)---创建对象
JS面向对象的程序设计
在网上找了几篇总结,发现都是没办法很好的将该章节的重要内容以及精华全部覆盖和解析,所以呢,看书才是最重要的,网上的文章只能作为一种辅助工具:
JavaScript函数表达式1
JavaScript函数表达式2
这章没啥好说,基础知识,知道有那个对象,知道该对象之下有什么方法即可,最重要的是要脑海里时刻有它们的影子,这样才有灵活去运用它们的基础:
JavaScript中的BOM对象1
JavaScript中的BOM对象2,这篇总结挺好的。
在开发过程中,我们经常需要将时间转换成自己所需要的格式,下面有一个较为通用的方法
/**
* 格式化日期
* @param date:日期对象
* @param fmt:需要返回的日期格式(yyyyMMdd yyyy-MM-dd yyyy/MM/dd yyyy.MM.dd)
* @returns {*}
*/
function formatDate (date, fmt) {
let o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
'S': date.getMilliseconds() // 毫秒
}
// 如果fmt存在4个'y'字符,则将yyyy替换为:年份;RegExp.$1表示匹配到的第一组数据即yyyy
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
for (let k in o) {
// M==5 ==> 005 ==>05;涉及到的语法:stringObject.substr(start,length),substr()方法可在字符串中抽取从start下标开始的指定数目的字符。
if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
return fmt
}
使用例子(部分)
视频来源:妙味课堂
视频年限:2013年
jQuery版本:2.0.3
(function(){
(21,94):定义了一些变量和函数,比如jQuery = function(){};
(96,283):给JQ对象添加一些方法和属性;
(285,347):extend JQ的继承方法;
(349,817):jQuery.extend() 扩展一些工具方法;
(877,2856):Sizzle 复杂选择器的实现;
(2880,3042):Callbacks 回调对象,函数的一个统一管理;
(3043,3183):Deferred 延迟对象,对异步的统一管理;
(3184,3295):support 功能检测;
(3308,3652):data() 数据缓存;
(3653,3797):queue() 队列管理;
(3803,4299):attr() prop() val() addClass()等,对元素属性的操作;
(4300,5128):on() trigger() 事件操作的相关方法;
(5140,6057):DOM操作,添加 删除 获取 包装 DOM筛选;
(6058,6620):css() 样式的操作;
(6621,7854):提交的数据和ajax() load() getJson();
(7855,8584):animate() 运动的方法;
(8585,8792):offset() 位置和尺寸的方法;
(8804,8821):JQ支持模块化的模式;
(8826):window.jQuery = window.$ = jQuery;
})();
源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
function getParamFromUrl(name) {
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
// window.location.search获取到链接中的参数,?gameId=5566&userId=8899
// window.location.search.substr(1)截取问号?后的内容,gameId=5566&userId=8899
// window.location.search.substr(1).match(reg)检索指定的值,返回一个数组,
// ["gameId=5566&", "", "5566", "&", index: 0, input: "gameId=5566&userId=8899", groups: undefined]
const r = window.location.search.substr(1).match(reg);
if (r != null) {
// unescape() 函数可对通过 escape() 编码的字符串进行解码。返回5566
return unescape(r[2]);
}
return null;
}
getParamFromUrl("gameId")
</script>
</body>
</html>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.