1. bind(),call(),apply() 具体指什么
bind(), call(), apply()
都是用于改变this指向的对象- 在函数中
this
指向的对象是window
,可以通过this
引用全局作用域之中的数据。 - 在对象中所定义的函数中,该函数中的
this
指向该对象,可以通过this引用该对象内的全体数据。 - 通过
bind(), call(), apply()
进行对象的绑定后,this
指向改为三者分别传入的对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>bind,apply,call</title>
</head>
<body>
<script>
var name = 'Tom', age = '17';
var person ={
name: 'John',
country:'USA',
address:'WashingTon DC',
myfun : function(from, to){
if(!from && !to){
console.log(this.name + " " + this.country);//打印结果: John USA (此处的this指向person)
} else{
console.log(this.name + " " + this.country + from +' ' + to);
}
}
}
function print(){
var tall = 170;
console.log(tall); //打印结果:170
console.log(this.tall);//打印结果:undefined
console.log(this.name);//打印结果:Tom
console.log(this.person.myfun())
}
print();
function printObject(object){
console.log(this);//当前this为window
console.log(window.name);//打印结果:Tom
console.log(this.tall);//打印结果:undefined
console.log(window.tall);//打印结果:undefined,window也只能访问全局变量,而不能访问局部
console.log(this.name);//打印结果:Tom
console.log(this.country);//打印结果:undefined
console.log(object.name);//打印结果:John
//console.log(this.person.myfun() + "11");
}
printObject(person);
var people ={
name:'White',
country:'China'
}
person.myfun.call(people);//打印结果:White China
person.myfun.apply(people);//打印结果:White China
person.myfun.bind(people)();//打印结果:White China
// 可以发现通过这三种方式,均是this 指向的对象发生的改变,由指向person 改为指向people.
//call() apply() bind()不同的传参方式
person.myfun.call(people,'大连','大阪');//打印结果:White China大连 大阪
person.myfun.apply(people,['大连','东京']);//打印结果:White China大连 东京
person.myfun.bind(people,['大连'],['名古屋'])();//White China大连 名古屋
</script>
</body>
</html>
补充:
- 在非严格模式下:如果不传参数,或者第一个参数是null或undefined,this都指向window。
- 第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefined
2.JS事件流
定义:DOM结构是一个树型结构,当一个HTML元素触发一个事件时,该事件会在元素结点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为 DOM 事件流。
这个传播的过程分为三个阶段:
- 事件捕获阶段(从根节点window到目标节点,即最近的、最精确的元素节点)
- 目标阶段(目标节点上的事件触发按代码执行顺序触发)
- 事件冒泡阶段(从目标节点到根节点)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<button>点击</button>
</div>
<script>
//事件在冒泡阶段触发
let div = document.getElementsByTagName('div')[0];
div.addEventListener('click', (e) => {
console.log('div')
})
//事件在捕获阶段触发
div.addEventListener('click' ,(e) =>{
console.log('div1')
},true)
//事件在冒泡阶段触发
let button = document.getElementsByTagName('button')[0];
button.addEventListener('click', (e) => {
console.log('button')
})
//事件在捕获阶段触发
button.addEventListener('click',(e)=>{
console.log('button1')
},true)
// button.addEventListener('click',(e)=>{
// console.log('button1')
// },{capture:true})
//依次输出: div1 button1 button div
//停止传播 e.stopPropagation()会让事件传播到目标阶段后停止传播。即阻止冒泡
button.addEventListener('click', (e) => {
e.stopPropagation()
console.log('button')
})
div.addEventListener('click', (e) => {
console.log('div1')
},true)
div.addEventListener('click', (e) => {
console.log('div2')
})
//依次输出: div1 button
//马上停止传播:event.stopImmediatePropagation();简言之停止后续所有的传播
</script>
</body>
</html>
3. 深拷贝和浅拷贝的区别
简而言之,浅拷贝得到的对象与被拷贝的对象之间仍存在关系,相互影响。深拷贝得到的对象与被拷贝的对象之间没有关系,不存在相互的影响。
//浅克隆
function shallowClone(obj) {
let cloneObj = {};
for (let i in obj) {
cloneObj[i] = obj[i];
}
return cloneObj;
}
//深克隆
function deepCopy(obj) {
if (typeof obj === 'object') {
var result = obj.constructor === Array ? [] : {};
for (var i in obj) {
result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
}
} else {
var result = obj;
}
return result;
}
变量提升
提升(Hoisting)是 JavaScript 将声明移至顶部的默认行为。
只提升声明至顶部,而不提升初始化信息
var x = 5; // 初始化 x
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
var y = 7; // 初始化 y
经过提升后
var x = 5; // 初始化 x
var y;
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
y = 7; // 初始化 y
let, const
声明的变量不会被提升
在严格模式“use strict"
下,不允许使用未经过声明的变量
instanceof, typeof的区别
typeof
主要用于基础数据类型(number, string, boolean,undefined
)的判断
const a = false;
typeof (a); //返回 boollean
instanceof
运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上。
语法:variable instanceof constructor
通过a instanceof b
可以判断a 是否为b的实例
class student {
constructor (name,age){
this.name = name;
this.age = age;
}
}
const stu = new Student('Tom','25');
console.log(stu instanceof Student);
//输出为true 即stu是Student的实例
[] instanceof Object //true
[] instanceof Array //true
如何解决由于原型链导致instanceof
的问题?
Array.isArray();
对数组进行检测
Array.isArray([]); //true
Object.prototype.toString.call( )
Object.prototype.toString.call([])
//返回"[object Array]"
Object.prototype.toString.call('')
//返回"[object String]"
Object.prototype.toString.call({})
//返回"[object Object]"
Object.prototype.toString.call(123)
//返回"[object Number]"