typeof和instanceof 都可以检测数据类型,typeof检测如果是基本数据类型返回对应的结果。如果检测是对象的话,默认返回一个object,所以无法区分那种对象。
typeof 数据
instanceof是用于判断指定的数据,是否满足和指定构造函数匹配,只要匹配就说明他是同一种数据类型,主要用于判断对象的类型,无法用于基本数据类型,基本数据类型不存在构造器
[] instanceof Array
{} instanceof Object
instanceof的原理就是获取左边数据的构造函数,用于和右边(指定的构造函数)进行判断是否相等。
如果左边获取到的构造函数不等于右边,并不会马上结束,循环继续找对象的原型的函数是否和右边相等,直到找完了原型链对象,都匹配不了,返回false
代码复现:
function myInstanceof(left, right) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if(typeof left !== 'object' || left === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while(true) {
if(proto === null) return false;
if(proto === right.prototype) return true;//找到相同原型对象,返回true
proto = Object.getPrototypeof(proto);
}
}
从上面可以看到,apply
、call
、bind
三者的区别在于:
this
对象指向this
要指向的对象,如果如果没有这个参数或参数为undefined
或null
,则默认指向全局window
apply
是数组,而call
是参数列表,且apply
和call
是一次性传入参数,而bind
可以分为多次传入bind
是返回绑定this之后的函数,apply
、call
则是立即执行内存泄漏不等于内存溢出。完全两个概念。内存泄漏可能导致内存溢出
内存泄漏指的就是代码运行过程中,变量使用完毕后无法被垃圾回收机制销毁(回收)。一直占这内存。这种情况称为内存泄漏。
常见的内存泄漏:
标准答案:
在javascript的世界中,所有的数据要进行处理,都要进行二进制的转换。
整数转化为二进制没有任何问题。但是小数转化二二进制就会出现无法整除的情况。
比如:
0.3-0.2 = 0.99999998
本身0.3和0.2
标准答案:
大文件上传上传遇到的问题,文件过大,上传很慢,上传中途可能出现网络异常、加上暂停功能解决续传的问题。
所以才出现了大文件断点续传。
思路:
本地通过<input type="file" onchange="">
change事件可以获取文件对象file【size、type、name】
前端获取file对象后,使用slice对文件进行切片操作。得到多个切片数组。
前端封装文件上传代码。通过promise.all的方式来进行批量上传。虽然js是单线程的语言。但是浏览器是多线程,可以一次性处理多个文件上传任务。
promise.all() //同时处理多个promise任务,当所有任务成功。all返回成功,但凡一个失败。all失败
promise.race() //同时处理多个promise任务,拿到最快的请求结果
promise.allsetlet() //同时处理多个promise任务,不管成功还是失败,都会返回结果。返回所有结果
如果需要暂停,需要使用axios提供的cancleToken来取消请求。
所有切片上传完毕后,在调用后端提供的合并接口,要求后端合并所有切片。返回结果给前端
前端拿到结果在提示用户上传成功
web攻击指的就是利用前端页面。或者前端身份信息。对服务区发起恶意的请求。
XSS (Cross Site Scripting) 跨站脚本攻击:
cookie
或者其他网站用于识别客户端身份的敏感信息。一旦获取到合法用户的信息后,攻击者甚至可以假冒合法用户与网站进行交互。<script>
标签,里面写死循环造成对服务器攻击,或者写入特殊的代码。CSRF(Cross-site request forgery)跨站请求伪造
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求
利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目
一个典型的CSRF攻击有着如下的流程:
SQL注入攻击:前端在输入框恶意输入sql语句,传递给后端,后端服务器如果在没有验证的情况,直接拿去进行sql拼接。就可能出现绕过身份,直接访问数据库。
递归实现一个深度拷贝,最核心的问题就是知道你每次克隆的属性是基本类型还是引用类型,
如果是基本类型直接返回结果,赋值给新对象,如果是引用类型,我们采用递归来生成新对象,在返回上一层对象
function deepClone(obj, hash = new Map()) {
if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== "object") return obj;
// 是对象的话就要进行深拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
标准:
事件代理和事件委托利用了冒泡机制来实现页面优化。
当需要绑定在组件身上的事件冒泡到父组件,我们可以在父组件统一处理业务
比如在React开发过程中,表格的每一行数据都添加删除功能。
如果你每一行数据都绑定一个点击事件,数据多了性能并不好。
可以在表格上面动态获取点击的按钮编号来实现删除。
标准:
this指向最核心的概念:
ajax就是浏览器提出的前端异步请求的一种技术。
核心代码如下:
const xmlhttp = new XMLHttpRequest()
//建立连接
xmlhttp.open(method, url, [async][, user][, password])
xmlhttp.open("GET","http://127.0.0.1:8002/users/findUser",false)
//发送请求
xmlhttp.send("username=xiaowang&password=123")
//得到响应结果
//监听浏览器状态码,一旦状态码发生变化,这个事件触发
xnlhttp.onreadystatechange = function(){
if(xmlhttp.status>=200 && xmlhttp.readystate==4){
const msg = xmlhttp.responseText
const data = JSON.parse(msg)
}
}
步骤:
axios是一个第三方的请求工具。
底层:ajax+promise进行封装。调用axios的api函数默认返回的就是promise对象。解决了回调地狱的问题。
并且还提供了请求拦截器、响应拦截器等等功能。