nvpKong

我并没有逃走,只是稍作休息。


  • 首页

  • 标签

  • 分类

  • 归档

  • 搜索

JS-BOM与DOM的区别与联系

发表于 2019-10-15 | 分类于 前端

DOM(文档对象模型)

DOM 是 W3C 标准,DOM的最根本对象是 document(window.document),这个对象实际上是 window 对象的属性,这个对象的独特之处是这个是唯一一个既属于 BOM 又属于 DOM 的对象。
DOM 是 HTML 和 XML 的应用程序接口(API)。DOM代表着被加载到浏览器窗口里的当前网页。

BOM(浏览器对象模型)

BOM 没有相关标准,BOM 的最核心对象是 window 对象。window 对象对应着浏览器窗口本身,这个对象的属性和方法通常被称为 BOM。
BOM 主要处理浏览器窗口和框架,不过通常浏览器特定的 JavaScript 扩展都被看做 BOM 的一部分。这些扩展包括:

  1. 弹出新的浏览器窗口
  2. 移动、关闭浏览器窗口以及调整窗口大小
  3. 提供 Web 浏览器详细信息的定位对象
  4. 提供用户屏幕分辨率详细信息的屏幕对象

BOM与DOM的联系

参考文献1
参考文献2

JS-原型和原型链

发表于 2019-10-11 | 分类于 前端

构造函数

1
2
3
4
5
6
7
8
9
10
//构造函数命名时,首字母要大写
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
// return this // 默认有这一行
}

var f = new Foo('zhaoxiaocou', 26)
// var f1 = new Foo('coucou', 27) // 创建多个对象

描述 new 一个对象的过程

  1. 创建一个新对象
  2. this 指向这个新对象
  3. 执行代码,即对this 赋值
  4. 返回this

原型规则

1、所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null”意外)。

1
2
3
4
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn () {}
fn.a = 100;

2、所有的引用类型(数组、对象、函数),都有一个_proto_属性(隐式原型),属性值是一个普通的对象。

1
2
3
console.log(obj._proto_);
console.log(arr._proto_);
console.log(fn._proto_);

3、所有的函数,都有一个prototype属性(显示原型),属性值也是一个普通的对象。

1
console.log(fn.prototype)

4、所有的引用类型(数组、对象、函数),_proto属性值指向它的构造函数的”prototype”属性值。

1
console.log(obj._proto_ === Object.prototype)

5、当试图得到一个引用类型(数组、对象、函数)的某个属性时,如果这个引用类型本身没有这个属性,那么会去它的__proto_(即它的构造函数的prototype)中寻找。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function () {
alert(this.name)
}
// 创建示例
var f = new Foo('zhaoxiaocou')
f.printName = function () {
console.log(this.name)
}
// 测试
f.printName()
f.alertName()

// toString() 方法返回一个表示该对象的字符串。
// toString() 返回 "[object type]",其中 type 是对象的类型。
console.log(f.toString()) //[object Object], 要去 f._proto_._proto_ 中去找

循环对象自身的属性

1
2
3
4
5
6
7
8
var item 
for (item in f) {
// 高级浏览器已经在for in中屏蔽了来自原型的属性
// 但是这里建议大家还是加上这个判断,保证程序的健壮性
if (f.hasOwnProperty(item)) {
console.log(item)
}
}

如何准确判断一个变量是数组类型

1
2
3
var arr = []
arr instanceof Array // true
typeof arr // object, typeof 是无法判断是否是数据的

原型链继承的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 写一个封装DOM查询的例子
function Elem(id) {
this.elem = document.getElementById(id)
}

Elem.prototype.html = function (val) {
var elem = this.elem
if (val) {
elem.innerHTML = val
return this // 链式操作
} else {
return elem.innerHTML
}
}

Elem.prototype.on = function (type, fn) {
var elem = this.elem
elem.addEventListener(type, fn)
}

var div1 = new Elem('div1')
// console.log(div1.html())

div1.html('<p>hello, weizhideziji.</p>')
div1.on('click', function () {
alert('clicked')
})

JS-事件冒泡和事件捕获

发表于 2019-10-10 | 分类于 前端

事件流

事件流描述的就是从页面中接收事件的顺序。而 IE 和 Netscape 提出了完全相反的事件流概念。IE事件流是事件冒泡,而Netscape的事件流就是事件捕获。

事件冒泡

IE的事件流叫做事件冒泡。即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。所有现代浏览器都支持事件冒泡,并且会将事件一直冒泡到window对象。

事件捕获

事件捕获的思想是不太具体的节点应该更早的接收到事件,而在最具体的节点应该最后接收到事件。事件捕获的用意在于事件到达预定目标之前捕获它。IE9+、Safari、Chrome、Opera和Firefox支持,且从window开始捕获(尽管DOM2级事件规范要求从document)。由于老版本浏览器不支持,所以很少有人使用事件捕获。

addEventListener的第三个参数

addEventListener的第三个参数就是为冒泡和捕获准备的.
addEventListener有三个参数:

1
element.addEventListener(event, function, useCapture)

第一个参数是需要绑定的事件
第二个参数是触发事件后要执行的函数
第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。

冒泡的案例

1
2
3
4
5
6
7
8
9
10
11
<div id="click_div">
<p id="click_p">click me!</p>
</div>
<script type="text/javascript">
click_div.addEventListener("click",function(e){
console.log("div 冒泡事件");
},false);
click_p.addEventListener("click",function(e){
console.log("p 冒泡事件");
},false);
</script>

当我们点击click_p的时候,执行结果如下:p 冒泡事件 -> div 冒泡事件

捕获的案例

1
2
3
4
5
6
7
8
9
10
11
12
<div id="click_div">
<p id="click_p">click me!</p>
</div>
<script type="text/javascript">
click_div.addEventListener("click",function(e){
console.log("div 捕获事件");
},true);

click_p.addEventListener("click",function(e){
console.log("p 捕获事件");
},true);
</script>

当我们点击click_p的时候,执行结果如下:div 捕获事件 -> p 捕获事件

事件捕获vs事件冒泡

当事件捕获和事件冒泡一起存在的情况,事件又是如何触发呢。

这里记被点击的DOM节点为target节点

  1. document 往 target节点,捕获前进,遇到注册的捕获事件立即触发执行
  2. 到达target节点,触发事件(到达target节点,触发事件(对于target节点上,捕获与冒泡事件的执行顺序取决于注册顺序)
  3. target节点 往 document 方向,冒泡前进,遇到注册的冒泡事件立即触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="click_div">
<p id="click_p">click me!</p>
</div>
<script type="text/javascript">
click_div.addEventListener("click",function(e){
console.log("div 冒泡事件");
},false);
click_p.addEventListener("click",function(e){
console.log("p 冒泡事件");
},false);

click_div.addEventListener("click",function(e){
console.log("div 捕获事件");
},true);

click_p.addEventListener("click",function(e){
console.log("p 捕获事件");
},true);
</script>

当我们点击click_p的时候,执行结果如下:div 捕获事件 -> p 冒泡事件 -> p 捕获事件 -> div 冒泡事件

阻止冒泡和捕获

方法一:
cancelBubble 已经不在标准中了,相信迟到会移除这一特性的。

1
event.cancelBubble = true; // IE下阻止冒泡、捕获

方法二:
event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件处理程序被执行。

1
event.stopPropagation() // 其它浏览器下阻止冒泡、捕获

阻止冒泡的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="click_div">
<p id="click_p">click me!</p>
</div>
<script type="text/javascript">
click_div.addEventListener("click",function(e){
console.log("div 冒泡事件");
},false);
click_p.addEventListener("click",function(e){
// e.cancelBubble = true
e.stopPropagation();
console.log("p 冒泡事件");
},false);
</script>

当我们点击click_p的时候,执行结果如下:p 冒泡事件

阻止捕获的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="click_div">
<p id="click_p">click me!</p>
</div>
<script type="text/javascript">
click_div.addEventListener("click",function(e){
// e.cancelBubble = true
e.stopPropagation();
console.log("div 捕获事件");
},true);

click_p.addEventListener("click",function(e){
console.log("p 捕获事件");
},true);
</script>

当我们点击click_p的时候,执行结果如下:div 捕获事件

参考文献1
参考文献2

JS-实现冒泡排序

发表于 2019-10-10 | 分类于 前端

对数组进行 冒泡排序,冒泡排序是容易理解的一种排序算法。

实现原理

数组中有 n 个数,比较每相邻两个数,如果前者大于后者,就把两个数交换位置;这样一来,第一轮就可以选出一个最大的数放在最后面;那么经过 n-1(数组的 length - 1) 轮,就完成了所有数的排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var arr = [3, 1, 9, 6]
function bubbleSort(arr) {
var max = arr.length - 1
for (var i = 0; i < max; i++) {
// 声明一个变量,作为标志位
var done = true;
// 根据外层for循环的i,逐渐减少内层for循环的次数
for (var j = 0; j < max - i; j++) {
if (arr[j]>arr[j + 1]) {
var temp = arr[j + 1]
arr[j + 1] = arr[j]
arr[j] = temp
done = false
}
}
if (done) {
break
}
}
return arr
}
bubbleSort(arr)

性能

时间复杂度: 平均时间复杂度O(n*n) 、最好情况O(n)、最差情况O(n*n)
空间复杂度: O(1)
稳定性:稳定

时间复杂度指的是一个算法执行所耗费的时间
空间复杂度指运行完一个程序所需内存的大小
稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面
不稳定指,如果a=b,a在b的前面,排序后可能会交换位置

总结

1、外层 for 循环控制循环次数
2、内层 for 循环进行两数交换,找每次的最大数,排到最后
3、设置一个标志位,减少不必要的循环
参考文献

JS-new 使用与不使用实例化对象的区别

发表于 2019-10-09 | 分类于 前端

JavaScript 中并没有真正的类,但 JavaScript 中有构造函数和 new 运算符。构造函数用来给实例对象初始化属性和值。任何 JavaScript 函数都可以用做构造函数,构造函数必须使用 new 运算符作为前缀来创建新的实例。
默认情况下,如果你的构造函数中没有返回任何内容,就会返回this——当前的上下文。

1
2
3
4
5
6
7
8
9
function Friend (name) {
this.name = name
}

var my1 = Friend('xiaochou')
var my2 = new Friend('xiaochou')

console.log(my1) // undefined
console.log(my2) // Friend {name: "xiaochou"}

第一种不是实例化,只是调用函数把返回值赋给变量。
第二种是构造函数式,即通过 new 运算符调用构造函数 Function 来创建函数,达到一种创建自定义对象 + 继承公有属性/方法的效果。

JS-递归算法计算一个数的阶乘

发表于 2019-10-08 | 分类于 前端

计算一个整数的阶乘
如果用字母n来代表一个整数,阶乘代表着所有小于或等于n的整数的乘积。
阶乘通常简写成 n!
例如:

1
5! = 1 * 2 * 3 * 4 * 5 = 120

递归算法是一种直接或者间接调用自身函数或者方法的算法。

1
2
3
4
5
6
7
8
9
function factorialize (num) {
// 函数内部继续调用,如果不做条件判断会无限递归下去
if (num > 0) {
return num * factorialize (num -1)
} else { // 防止factorialize(1)没有值,当num=1时,factorialize(1)=1
return 1
}
}
factorialize(3)

JS-随机数 Math 对象

发表于 2019-10-06 | 分类于 前端

JavaScript Math 对象

Math 对象用于执行数学任务。
注释:Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数,不是某个对象的方法。您无需创建它,通过把 Math 作为对象使用就可以调用其所有属性和方法。

ceil() 方法可对一个数进行上舍入。返回值大于等于 x,并且与它最接近的整数。

1
Math.ceil(x)

floor() 方法可对一个数进行下舍入。返回值小于等于 x,且与 x 最接近的整数。

1
Math.floor(x)

round() 方法可把一个数字舍入为最接近的整数。返回值与 x 最接近的整数。

1
Math.round(x)

random() 方法可返回介于 0 ~ 1 之间的一个随机数。返回值0.0 ~ 1.0 之间的一个伪随机数。

1
Math.random()

获取随机数,要求是长度一致的字符串格式

1
2
3
4
5
6
var random = Math.random()
// 后面加上 10 个零,防止 random 是空字符串导致 slice() 方法报错
random = random + '0000000000'
// random 的长度必须能被 slice() 方法截取的,否则会报错
random = random.slice(0, 10)
console.log(random)

参考文献

JS-数组API

发表于 2019-10-06 | 分类于 前端

forEach 遍历所有元素

1
2
3
4
5
var arr = [1, 2, 3]
arr.forEach(function (item, index) {
// 遍历数组的所有元素
console.log(index, item)
})

every 判断所有元素是否都符合条件

1
2
3
4
5
6
7
8
var arr = [1, 2, 3]
var resulet = arr.every(function (item, index) {
// 用来判断所有的数组元素,都满足一个条件
if (item < 4) {
return true
}
})
console.log(resulet)

some 判断是否有至少一个元素符合条件

1
2
3
4
5
6
7
8
var arr = [1, 2, 3]
var resulet = arr.some(function (item, index) {
// 用来判断所有的数组元素,只要有一个满足条件即可
if (item < 2) {
return true
}
})
console.log(resulet)

sort 排序

1
2
3
4
5
6
7
8
9
var arr = [1, 5, 4, 2, 3]
var arr2 = arr.sort(function (a, b) {
// 从小到大排序
// return a - b

// 从大到小排序
return b - a
})
console.log(arr2)

map 对元素重新组装,生成新数组

1
2
3
4
5
6
var arr = [1, 2, 3, 4, 5]
var arr2 = arr.map(function (item, index) {
// 将元素重新组装,并返回
return '<b>' + item + '</b>'
})
console.log(arr2)

filter 过滤符合条件的元素

1
2
3
4
5
6
7
8
var arr = [1, 2, 3, 4, 5]
var arr2 = arr.filter(function (item, index) {
// 通过某一个条件过滤数组
if (item >= 2) {
return true
}
})
console.log(arr2)

写一个能遍历对象和数组的forEach函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function forEach(obj, fn) {
var key
// 准确判断是不是数组
if (obj instanceof Array) {
obj.forEach(function (item, index) {
fn(index, item)
})
} else {
// 不是数组就是对象
for (key in obj) {
fn(key, obj[key])
}
}
}

var arr = [1, 2, 3]
// 注意,这里参数的顺序换了,为了和对象的遍历格式一致
forEach(arr, function (index, item) {
console.log(index, item)
})

var obj = {x: 100, y: 200}
forEach(obj, function (key, value) {
console.log(key, value)
})

JS-日期 Date 对象

发表于 2019-10-06 | 分类于 前端

JavaScript Date 对象

Date 对象用于处理日期和时间。
注释:Date 对象会自动把当前日期和时间保存为其初始值。

1
2
3
4
5
6
7
8
9
10
11
Date.now() // 获取当前时间毫秒数

var dt = new Date()
dt.getTime() // 获取毫秒数
dt.getFullYear() // 年
dt.getMonth() // 月 (0 - 11)
dt.getDate() // 日 (0 - 31)

dt.getHours() // 小时 (0 - 23)
dt.getMinutes() // 分钟 (0 - 59)
dt.getSeconds() // 秒 (0 - 59)

获取2019-08-10格式的日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function formatDate (dt) {
// 如果这个参数没有的话
if (!dt) {
dt = new Date()
}
var year = dt.getFullYear()
var month = dt.getMonth() + 1
var date = dt.getDate()
if (month < 10) {
// 强制类型转换
month = '0' + month
}
if (date < 10) {
// 强制类型转换
date = '0' + date
}
// 强制类型转换
return year + '-' + month + '-' + date
}

var dt = new Date()
var formatDate = formatDate(dt)
console.log(formatDate)

参考文献

Windows 中通过命令行新建、删除文件夹和文件

发表于 2019-09-26 | 分类于 命令行

windows cmd 新建、删除文件夹和文件

一:文件夹命令行
1.新建文件夹
方式一:md【盘符:\】【路径\】新目录

1
2
md c:\test\*
例如:md c:\test\newtest

方式二:使用 cmd 进入需要新建文件夹的根目录下,使用 md 或者mkdir 直接创建文件夹 newtest

1
2
md * 或者 mkdir *
例如:md newtest 或者 mkdir newtest

2.删除文件夹
使用 cmd 进入需要删除文件夹的根目录下

1
2
rd *
例如:rd newtest

二:文件命令行
1.新建文件(创建任意后缀的文件)
方式一:新建空文件 type nul>.

1
2
type nul > *.*  或者 type nul>.*
例如:type nul> newtest.txt 或者 type nul>.txt

方式二:新建非空文件 echo [fileContent]>.

1
2
echo 文件中的内容>*.*
例如:echo 'Hello World'>newtest.txt

2.删除文件

1
2
del *.*
例如:del newtest.txt

cmd 基本命令和创建文件

(1). 返回上一级目录:cd .. (cd 与 .. 之间有一空格)。

(2). 进入某一目录:cd cmd (进入 cmd 目录)。

(3). 清屏:cls。

(4). 显示当前路径:cd。

windows git bash 新建、删除文件夹和文件

一:文件夹命令行
1.新建文件夹

1
2
mkdir *
例如:mkdir 文件夹名

2.删除文件夹

1
2
rm -r *
例如:rm -r 文件夹名

二:文件命令行
1.新建文件
方式一:touch .,直接新建一个文件

1
2
touch *.*
例如: touch 文件名.格式

方式二:vi .,新建一个文件并进入编辑状态(如果文件已存在,则直接进入编辑状态)

1
2
vi *.*
例如:vi 文件名.格式

注释:vi 其实是 linux 的一个文本编辑器。所以 vi+文件名.格式 后,其实是进入 vi 程序了。vi 有两种模式,编辑模式和命令模式。
在命令模式下,我们可以直接按 i ,此时就会切换到编辑模式,如下图,下方有个insert,此时可以直接修改文本内容。

在编辑模式下,按 esc 就可以切换到命令模式。

按下 “ESC” 键,退出编辑模式,切换到命令模式。
在命令模式下键入”ZZ”或者”:wq”保存修改并且退出 vi。
如果只想保存文件,则键入”:w”,回车后底行会提示写入操作结果,并保持停留在命令模式。

2.删除文件

1
2
rm *.*
例如:rm 文件名.格式

git 基本命令和创建文件

(1). 返回上一级目录:cd .. (cd 与 .. 之间有一空格)。

(2). 进入某一目录:cd git (进入 git 目录)。

(3). 清屏:reset。

(4). 显示当前路径:pwd。

参考文献1
参考文献2
参考文献3

123

nvpKong

29 日志
3 分类
9 标签
© 2019 nvpKong
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4