JS面试题 __Glimmer
谈谈对前端安全的理解,有什么,怎么防范?
前端安全问题主要有XSS、CSRF攻击
XSS:跨站脚本攻击
它允许用户将恶意代码植入到提供给其他用户使用的页面中,可以简单的理解为一种javascript代码注入。
XSS的防御措施:
1.过滤转义输入输出
2.避免使用eval、new Function等执行字符串的方法,除非确定字符串和用户输入无关
3.使用cookie的httpOnly属性,加上了这个属性的cookie字段,js是无法进行读写的
4.使用innerHTML、document.write的时候,如果数据是用户输入的,那么需要对象关键字符进行过滤与转义
CSRF:跨站请求伪造
其实就是网站中的一些提交行为,被黑客利用,在你访问黑客的网站的时候进行操作,会被操作到其他网站上;
CSRF防御措施:
1.检测http referer是否是同域名
2.避免登录的session长时间存储在客户端中
3.关键请求使用验证码或者token机制
其他的一些攻击方法还有HTTP劫持、界面操作劫持
JS实现继承的几种方式
借用构造函数实现继承
function Parent1(){
this.name = "parent1"
}
function Child1(){
Parent1.call(this);
this.type = "child1";
}
缺点:Child1无法继承Parent1的原型对象,并没有真正的实现继承(部分继承),
借用原型链实现继承
function Parent2(){
this.name = "parent2";
this.play = [1,2,3];
}
function Child2(){
this.type = "child2";
}
Child2.prototype = new Parent2();
缺点:原型对象的属性是共享的
组合式继承
function Parent3(){
this.name = "parent3";
this.play = [1,2,3];
}
function Child3(){
Parent3.call(this);
this.type = "child3";
}
Child3.prototype = Object.create(Parent3.prototype);
Child3.prototype.constructor = Child3;
第四种方法,利用一个空对象作为中介;
第五种拷贝继承;
原型与闭包相关问题
原型是什么
原型就是一个普通的对象,每个对象都有一个原型(Object除外),原型能存储我们的方法,构造函数创建出来的实例对象能够引用原型中的方法。
查看原型
以前一般使用对象的proto属性,ES6推出后,推荐用Object.getPrototypeOf()方法来获取对象的原型
闭包是什么?
专业说法:当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。
还可以这么理解: 闭包就是一个具有封闭功能与包裹功能的结构,是为了实现具有私有访问空间的函数的,函数可以构成闭包,因为函数内部定义的数据函数外部无法访问,即函数具有封闭性;函数可以封装代码即具有包裹性,所以函数可以构成闭包。
创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
闭包的特性
闭包有三个特性:
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收
闭包有什么用,使用场景
当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会“污染”全局的变量时,就可以用闭包来定义这个模块。
闭包的缺点
闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
函数套函数就是闭包吗?
不是!当一个内部函数被其外部函数之外的变量引用时,才会形成了一个闭包 ;
闭包面试题
function fun(n,o) {
console.log(o);
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3);//undefined,0,1,2
var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,0,1,1
//问:三行a,b,c的输出分别是什么?
深拷贝与浅拷贝
实现浅拷贝
var obj1={a:10,b:20,c:30};
var obj2=obj1;
obj2.b=100;
console.log(obj1);
//{a:10,b:100,c:30};<- b的值被修改
console.log(obj2);
//{a:10,b:100,c:30};
实现深拷贝
var obj1={a:10,b:20,c:30};
var obj2={a:obj1.a,b:obj1.b,c:obj1.c};
obj2.b=100;
console.log(obj1);
//{a:10,b:20,c:30};<- b的值没有被修改
console.log(obj2);
//{a:10,b:100,c:30};
深拷贝例题:
var arr=[1,2,[3,4,[5,6,[7,8]]],[9,10]];
var arr2=[];
function fn(a,b){
for(var i=0;i<b.length;i++){
if(typeof b[i]=="number"){
a.push(b[i]);
}else{
var arr3=[];
fn(arr3,b[i]);
a.push(arr3);
}
}
}
fn(arr2,arr)
arr[2].push(5);
console.log(arr2)
代码优化基本方法
减少HTTP请求
HTML优化:
- 使用语义化标签
- 减少iframe:iframe是SEO的大忌,iframe有好处也有弊端
- 避免重定向
CSS优化:
- 布局代码写前面
- 删除空样式
- 不滥用浮动,字体,需要加载的网络字体根据网站需求再添加
- 选择器性能优化
- 避免使用表达式,避免用id写样式
js优化:
- 压缩
- 减少重复代码
图片优化:
- 使用WebP
- 图片合并,CSS sprite技术
减少DOM操作
- 缓存已经访问过的元素
- "离线"更新节点, 再将它们添加到树中
- 避免使用 JavaScript 输出页面布局--应该是CSS的事儿
使用JSON格式来进行数据交换 使用CDN加速
使用HTTP缓存:添加 Expires 或 Cache-Control 信息头
使用DNS预解析
Chrome内置了DNS Prefetching技术, Firefox 3.5 也引入了这一特性,由于Chrome和Firefox 3.5本身对DNS预解析做了相应优化设置,所以设置DNS预解析的不良影响之一就是可能会降低Google Chrome浏览器及火狐Firefox 3.5浏览器的用户体验。
预解析的实现:
1.用meta信息来告知浏览器, 当前页面要做DNS预解析:
2.在页面header中使用link标签来强制对DNS预解析: