一. JS等基础
-
深浅拷贝
浅拷贝:
对于基本类型,浅拷贝是对值的复制(改一个值,不会改变另一个值)。对于引用类型,浅拷贝是对对象地址的复制, 也就是拷贝的结果是两个对象指向同一个地址(修改一个对象的属性,会改变另一个对象的属性)。
深拷贝:
深拷贝开辟一个新的栈,两个对象对应两个不同的地址(修改一个对象的属性,不会改变另一个对象的属性)。
这个问题通常可以通过 JSON.parse(JSON.stringify(object)) 来解决。
let a = {
age: 1,
jobs: {
first: 'JS'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'JAVA'
console.log(b.jobs.first)
但是该方法也是有局限性的:
会忽略 undefined、会忽略 symbol、不能序列化函数、不能解决循环引用的对象
-
原型 原型链
什么是原型:
原型是一个函数,其中的prototype是原型对象。在原型对象中其中定义了一些公用的属性和方法
重点:
1.每一个函数对象都有一个prototype属性,但是普通对象是没有的。
2.prototype原型对象中有一个constructor构造函数,指向这个函数
3.每个对象都有一个__proto__的内部属性,指向所对应的构造函数的原型对象,原型链是基于__proto__的。
原型的主要作用就是实现继承与扩展对象。
什么是原型链:
原型的__proto__指向其构造函数,其构造函数的__proto__有指向了构造函数的构造函数。这个连接过程或路线 被称为原型链。
重点:原型链的链头是Object。原型链是原型对象创建过程中的历史记录。
-
闭包
外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象,这就是闭包的重要概念。
举个例子:
function test(){
let a = "aaaa";
let b = function(){
return a;
};
return b();
}
console.log(test());
通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。
闭包的另一种使用场景:
function test(){
let a=0;
this.getA = function(){
return a;
};
this.addA = function(){
a++;
}
}
let b = new test();
console.log(b.getA());
b.addA();
console.log(b.getA());
b.addA();
console.log(b.getA());
此时 变量a会一直存在,但是无法直接访问。
-
继承有几种,是什么样的。
--原型链继承
这种方式关键在于:子类型的原型为父类型的一个实例对象。
参考网上的一个例子:
function Person(name, age) {
this.name = name,
this.age = age,
this.play = [1, 2, 3]
this.setName = function () {}
}
Person.prototype.setAge = function () {}
function Student(price) {
this.price = price
this.setScore = function () {}
}
Student.prototype = new Person()
var s1 = new Student(100)
var s2 = new Student(200)
console.log(s1,s2)
特点:
父类新增原型方法/原型属性,子类都能访问到
简单,易于实现
缺点:
无法实现多继承
来自原型对象的所有属性被所有实例共享
创建子类实例时,无法向父类构造函数传参
要想为子类新增属性和方法,必须要在Student.prototype = new Person() 之后执行,不能放到构造器中
方式二: 借用构造函数继承
方式三: 原型链+借用构造函数的组合继承
方式四: 组合继承
方式五:ES6中class 的继承
-
内存泄漏:什么原因会有内存泄漏。怎么解决或预防
JavaScript 是一个有垃圾回收机制的语言,我们不需要手动回收内存。当本应在垃圾回收周期中清理的内存中的对象,通过另一个对象的无意引用从根保持可访问状态时,就会发生内存泄漏,并可能导致性能下降的后果。
全局变量,闭包,定时器,事件监听
待完善:
-
基础类型有哪些,怎么判断。 引用类型有哪些?
String number boolean undefined null symbol
typeof能判断大部分情况
引用类型 object Date、Array、RegExp
-
1/0 什么结果 0.1+0.2为什么不等于0.3
①0/0 NAN 1/0 Infinity(比0大的数除以0,则会得到无穷大,所以 js 用 Infinity 来显示出来) 1/00 NAN
②因为js运算机制 是转为2进制计算 在转为10进制展示。
而0.1转为2进制是(小数部分2 取整数部分)
0.12= 0.2 取 0
0.22 = 0.4 取 0
0.42 = 0.8 取 0
0.82 = 1.6 取 1
0.62 = 1.2 1
0.22 = 0.4 取 0
0.42 = 0.8 取 0
0.82 = 1.6 取 1
0.6*2 = 1.2 1
循环
00011 0011(循环0011)
0.2同样如此
相加转为十进制以后 0.30000000000000004
二. CSS
待完善
三. VUE
四. React
五. Webpack
六. es6相关
七. 其他
MVVM与MVC最大的区别MVVM实现了View和Model的自动同步,不用再自己手动操作Dom元素了,即Model变化时View可以实时更新,View变化也能让Model改变。
-
跨域
跨域的解决方案
1).jsonp
可替换元素 (含有src属性)是不受跨域影响的 例如 <script>、<img> 、<iframe>
核心就是动态添加script
jsonp的缺点 缺点:
只能发送get请求,不支持post put delete 不安全,容易造成xss攻击,
原因: 去请求别的域,得到别的域返回的数据,万一是个脚本,那就注入到自己的代码里了。 现在基本不采用了。
2).iframe
3).postMessage
这是H5引入的一个API,可以实现跨文档、多窗口、跨域消息的传递。
message方法 window.addEventListener(‘message’,function(e){ console.log(e.data); })
该方法的参数e中有几个属性必须了解: e.data 指的是传递过来的数据 e.origin 指的是发射源的域
4).CORS 跨域资源共享
CORS即“跨域资源共享”,这是一种最常用的跨域实现方式,一般需要后端人员在处理请求数据的时候,添加允许跨域的相关请求头信息。大致思路是这样的:首先获取请求对象的信息,比如Origin字段,通过预先配置的参数判断请求是否合法,然后设置相应对象response的头信息,实现跨域资源请求。
前后端配置 withCredentials = true // 带上cookie
后端配置允许跨域访问的域名
5)nginx
使用反向代理
6)document.domain
这个方法使用极其简单,但是也有较大的限制,主要用于主域相同的域之间的数据通信。
7)window.name
window.name有如下特征: 1. 每个窗口都有自己独立的window.name 2. 当一个页面载入多个页面的时候,共享同一个window.name,该页面以及所有载入的页面都可以对共享的window.name进行读写。 3. window.name一直会存在当前窗口中,即时有新页面载入,window.name也不会变化(所以本例中,c页面给window.name一个值,即便c页面销毁,a页面依旧能够得到window.name,且该值就是c页面给的这个值) 4. window.name可以存储不超过2M的数据,传递的数据都会变成string类型。
8)webSocket
本身不存在跨域问题,所以我们可以利用webSocket来进行非同源之间的通信
-
前端安全:有哪些安全问题?解决办法
XSS: (Cross-site scripting),是一种代码注入攻击; 攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。 XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。 根据攻击脚本引入的位置,XSS 可以分为三类。
XSS 攻击的预防
一般使用对 HTML 字符编码转义来防范 XSS ,比如
建议使用成熟的库来防范
保护好用户的 Cookie ,加上 HttpOnly 属性,加上了这个属性的 Cookie 字段,js 是无法进行读写的
CSRF: CSRF(Cross-site request forgery)中文名称跨站请求伪造,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
因为伪造 GET 请求的难度比 POST 请求的难度小(打开一个 URL 或是请求一个资源便是一个 GET 请求),所以对于涉及业务操作的接口,尽量用 POST 请求,另外,CSRF 的防御手段可以根据 CSRF 的特点来入手
cookies 设置 sameSite
* 验证 csrf token
这是目前相对成熟的方案之一,具体的做法是:
服务端随机生成 token,保存在服务端 session 中,同时保存到客户端中,客户端发送请求时,把 token 带到 HTTP 请求头或参数中,服务端接收到请求,验证请求中的 token 与session 中的是否一致
-
问对方公司的问题
①.我进去以后会安排到哪个团队 主要产品是什么样的?
产品的前后端技术体系大概有用到什么?
②.贵公司的管理架构是什么样的?
③.日常管理风格是什么样?有借助工具来管理么?类似敏捷管理的看板
④.公司文化:如加班 如下午茶 如生日 如过节 如旅游等等
⑤.加班出差问题
⑥ 我的日常工作是什么?
⑦团队里面初级和高级工程师的比例是多少?(有计划改变吗)
⑧我入职的岗位是新增还是接替之前离职的同事?(是否有技术债需要还)?
⑨公司常用的技术栈是什么?
⑩晋升流程是怎样的?
?月薪、年终(或年薪)绩效构成,五险一金 医社保交费比例和基数?
?带薪休假时间有多久?还有什么福利?