对象
类对象:是对象类型的子类型
- 数组(Array)类
- 函数(Function)类
- 日期(Date)类
- 正则(RegExp)类
- 错误(Error)类
判断数据类型的方法
- typeof 缺点: 无法区分Object和Array等引用数据类型
console.log(typeof 1)
console.log(typeof 'a')
console.log(typeof new Object()) //object
console.log(typeof new Array()) //object
console.log(typeof null) //object
console.log(typeof undefined) // undefined
- instanceof
- 定义: 判断A是否是B的实例
- 缺点:
- 只能判断引用数据类型
- 无法判断null和undefined
console.log(1 instanceof Number) // false
console.log('a' instanceof String) // false
console.log(new Object() instanceof Object) // true
console.log(new Array() instanceof Array) // true
console.log(null instanceof Object) //false
console.log(undefined instanceof Object) //false
- constructor 缺点:无法判断null和undefined
let xx = 1
console.log(xx.constructor === Number) // true
console.log('a'.constructor === String) //true
console.log(new Object().constructor === Object) //true
console.log(new Array().constructor === Array) //true
let x = null
// console.log(x.constructor) //TypeError: Cannot read property 'constructor' of null
let y = undefined
// console.log(y.constructor) //TypeError: Cannot read property 'constructor' of undefined
- Object.prototype.toString().call()
console.log(Object.prototype.toString.call(1)) //[object Number]
console.log(Object.prototype.toString.call('a')) //[object String]
console.log(Object.prototype.toString.call(new Object)) //[object Object]
console.log(Object.prototype.toString.call(new Array)) //[object Array]
console.log(Object.prototype.toString.call(null)) //[object Null]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
原型和原型指针
- JavaScript所有对象都有一个__proto__(原型指针)属性;
- 对象的__proto__(原型指针) 指向 构造函数的prototype(原型);
var obj = new Object()
obj.__proto__ === Object.prototype
function fun(){}
fun.__proto__ === Function.prototype
var f = new fun()
f.__proto__ === fun.prototype
fun.prototype.__proto__ === Object.prototype
Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null
实现继承
作用域和作用域链
- 作用域的定义
- 作用域是可访问变量的结合。
- 在JavaScript中,对象和函数同样也是变量;
- 在JavaScript中,作用域是可访问变量、对象、函数的集合。
- 局部作用域
- 变量在函数内声明,变量为局部作用域;
- 局部变量可能再函数内部访问;
- 局部变量在函数开始执行时创建,函数执行后局部变量会自动销毁。
- 全局作用域
- 变量在函数外定义,即为全局变量;
- 全局变量有全局作用域,网页中所有的脚本和函数均可使用;
- 如果变量在函数中没有声明(没有使用var关键字),该变量为全局变量。
- 块级作用域
- ES6之前,没有块级作用域的概念;
- ES6可以使用let关键字来实现块级作用域;
- let声明的变量只在let命令所在的代码块{}内有效。
- 变量的生命周期
- js变量生命周期在它声明时初始化;
- 局部变量在函数执行完毕后销毁;
- 全局变量在页面关闭后销毁。
- 作用域链
- 一般情况下,变量是在定义这个变量的函数作用域中取值,但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
- 在JavaScript执行过程中,其作用域链是由词法作用域决定的。
- 词法作用域是由代码在函数声明的位置来决定的,所以词法作用域是静态作用域,通过它能够预测代码在执行过程中如何查找标识符。
function bar(){
console.log(myName) // yanessa
}
function foo(){
var myName = "ysg"
bar()
}
var myName = "yanessa"
foo()
闭包
参考链接: juejin.cn/post/695791…
- JavaScript除了静态作用域链外,还有一个特点就是函数可以作为返回值。这就导致一个问题,本来按照顺序创建调用一层层函数,按顺序创建和销毁作用域挺好的,但是如果内层函数返回了或者通过别的暴露出去了,那么外层函数销毁,内层函数却没有销毁,这时候该怎么处理作用域,父作用域销不销毁?
- 针对上叙情况,JavaScript就设计了闭包的机制。
- 静态作用域链中的父作用域先于子作用域销毁怎么解决?
- 父作用域要不要销毁?是不是父作用域不销毁就行了?
- 不行的,父作用域中很多东西和子函数无关,为啥因为子函数没有结束就一直常驻内存,这样肯定有性能问题,所以还是要销毁。但是销毁父作用域不能影响子函数,所以要创建一个对象,把子函数内引用的父作用域的变量打包起来,给子函数打包带走。
DOM事件流
-
DOM事件流的三个阶段
- 捕获阶段
- 目标阶段
- 冒泡阶段:事件从目标节点自下而上向window对象传播的阶段。
-
事件句柄
事件句柄(又称事件处理函数),是指事件发生时要进行的操作。
-
addEventListener的useCapture
- useCapture为addEventListener的第三个参数
- usecapture=true,事件句柄在捕获阶段执行
- useCapture=false 默认,事件句柄在冒泡阶段执行
<body>
<div id="father">
<div id="son">1</div>
</div>
<script>
const father = document.getElementById('father')
father.addEventListener('click', function(e){
console.log("点击父元素", e.target)
}, false)
const son = document.getElementById('son')
son.addEventListener('click', function(e){
console.log("点击子元素", e.target)
})
</script>
</body>
如上:当father的click事件的useCapture为false时,输出如下:
点击子元素 <div id="son">1</div>
点击父元素 <div id="son">1</div>
当father的click事件的useCapture为true时,输入如下:
点击父元素 <div id="son">1</div>
点击子元素 <div id="son">1</div>
-
event.preventDefaults()
如果调用这个方法,默认事件行为将不再触发。
什么是默认事件呢?例如表单一点击提交按钮(submit)跳转页面、a标签默认页面跳转或锚点定位等。
很多时候我们使用a标签仅仅是想当做一个普通的按钮,点击实现一个功能,不想页面跳转,也不想描点定位。
兼容性:
// prevent阻止
function preventDefault(){
var ev = this.event
if(ev.preventDefault){
ev.preventDefault()
}else{
ev.returnValue = false
}
}
-
event.stopPropagation() & event.stopImmediatePropagation()
当事件句柄在捕获阶段执行时,stopPropagation阻止的是事件捕获;
当事件句柄在冒泡阶段执行,stopPropagation阻止的是事件冒泡;
event.stopPropagation()只会阻止冒泡或者是捕获,event.stopImmediatePropagation()除此之外还会阻止该元素的其他事件发送。
兼容性:
// propagation传播
function stopPropagation(){
var ev = this.event
if(ev.stopPropagation){
ev.stopPropagation()
}else{
ev.cancelBubble = true
}
}