一、继承
1.原型继承
2.借用构造函数继承
3.组合式继承(1+2)
4.寄生式继承
5.寄生组合式继承(1+2+4)
1.原型继承
子类的原型指向父类的一个实例
原型继承的缺点:
1.父类的引用类型属性会被所有子类实例共享,任何一个子类实例修改了父类的引用类型属性,其他子类实例都会受到影响
2.创建子类实例的时候,不能向父类传参
Child.prototype = new Father();
var child1 = new Child();
2.借用构造函数继承
用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制)
优点:
1.避免了引用类型属性被所有实例共享
2.可以向父类传参
缺点:
1.方法必须定义在构造函数中
2.每创建一个实例都会创建一遍方法
function Child(name) {
this.name = name;
Father.call(this,name);
}
3.组合继承(1和2的结合)
父类的构造函数会被调用两次
function Child(name,age) {
Father.call(this,name,age);
}
Child.prototype = new Father();
4.寄生式继承
(创建一个封装的函数来增强原有对象的属性,跟借用构造函数一样,每个实例都会创建一遍方法)
function createObj(o) {
var clone = object.create(o);
clone.sayName = function () {
console.log('hello');
}
return clone;
}
var father = {
name: '人',
nation: '中国'
}
var son = createObj(father);
// son继承了father,拥有father的属性,同时还拥有sayName的方法
console.log(son);
5.寄生组合式继承
// 原型+借用构造函数+寄生
function Person() {
console.log(22);
this.class = '人类';
}
// 原型继承模式
Person.prototype.say = function() {
console.log(this.name);
}
/**
* 寄生 Man.prototype.__proto__ === Person.prototype;
* Man的父亲的父亲 === Person的父亲
*/
Man.prototype = Object.create(Person.prototype);
Man.prototype.constructor = Man;
function Man(name, age) {
this.name = name;
this.age = age;
// 借用构造函数模式
Person.call(this);
}
var man = new Man('张三丰', 100);
console.log(man);
6.es6继承
二、原型和原型链
https://www.cnblogs.com/zhuanzhuanfe/p/9707164.html
每一个构造函数都有一个prototype属性,指向了它的原型
每一个实例有一个proto属性,这个属性指向了它的原型,原型上还有proto,指向了它父类的原型,一直到Object.prototype为止,所有Object的原型,是一个对象的终极原型
访问实例的一个属性,会先从实例内部查找,若没有,就到它的原型去查找,还没有,就继续向父一级原型查找,一直查找到Object.prototype位置,若有,就返回,没有在返回undefined
每个函数都有一个prototype属性
三、闭包
(闭包是指有权访问另一个函数作用域中的变量的函数)
闭包的使用场景
1.封装私有变量
2.模仿块级作用域
(function () {
for(var i=0; i<10; i++){
console.info(i)
}
})()
alert(i); // 会报错
将i变成块级作用域
3.实现js模块
function Common(window) {
var DEBUG = "debug";
/**
* 打印日志
* @param args
*/
function log(args) {
console.log(args);
}
/**
* debug 利用闭包
* @param args
*/
function debug(args) {
console.log(DEBUG + args);
}
/**
* 编写
* @param args
*/
function write(args) {
document.write(args);
}
return {
log: log,
debug: debug,
write: write
};
}
//调用
var common = Common(window);
common.log("121");
common.debug(12232);
common.write("dadsa");
四、深浅拷贝
(1) 定义
浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用(改变其中一个,另外一个就紧跟着改变)
深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”)
浅拷贝:= 直接赋值
深拷贝:
拷贝数组:第一层
1.slice
2.concat
3.循环
4.es6扩展运算符
拷贝对象:第一层
1.赋原值
var obj = {
name:'wsscat',
age:0
}
var obj2 = new Object();
obj2.name = obj.name;
obj2.age = obj.age
- Object.assign:用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),并返回合并后的target
var obj = {
name: '彭湖湾',
job: '学生'
}
var copyObj = Object.assign({}, obj);
3.扩展运算符
let obj1 = {a:2, b:3};
let obj2 = {...obj1};
深拷贝多层
1.封装一个方法
2.JSON
var objStr = JSON.stringify(obj);
var obj2 = JSON.parse(objStr);
五、new关键字
(创建对象,创建实例)
1、在函数里面创建一个对象obj
2、将函数里面的this指向创建的那个对象obj
3、返回这个obj对象
六、浏览器内核
七、let var const
var:全局和局部 (不能跨函数,可以跨块)
let:定义变量(不能重复声明,块级作用域)
const:定义常量(不能重复声明,声明必须赋值,地址不能改变,块级作用域)
当在函数内没加var时 此时a为全局变量
八、document.ready和document.onload
1.document.ready:在DOM加载完成后就可以可以对DOM进行操作。一般情况一个页面响应加载的顺序是,域名解析-加载html-加载js和css-加载图片等其他信息。那么Dom Ready应该在“加载js和css”和“加载图片等其他信息”之间,就可以操作Dom了。
2.onload:在document文档加载完成后就可以可以对DOM进行操作,document文档包括了加载图片等其他信息。那么Dom Load就是在页面响应加载的顺序中的“加载图片等其他信息”之后,就可以操作Dom了。
九、this的指向
第一种:方法调用
var age = 38;
var obj = {
age: 18,
getAge: function() {
console.log(this.age);
}
};
obj.getAge(); // this指向obj,所以this.age的值是18
--------------------------------------------------
// 变式:
var fn = obj.getAge;
fn(); // window在调用,所以值是38
第二种:函数调用(this指向的是window)
var age = 38;
var obj = {
age: 18,
getAge: function() {
var fn = function() {
console.log(this.age);
};
fn();
}
};
obj.getAge();
第三种:构造函数内this指向
// new的原理
1、在函数里面创建一个对象obj
2、将函数里面的this指向创建的那个对象obj
3、返回这个obj对象
function Person(name,age){
// this指向了创建出来的对象person
this.name = name;
this.age = age;
}
var person = new Person();
第四种:上下文调用模式,this指向谁?指向的是传入的对象
call、apply和bind
十、跨域和jsonp
知其然知其所以然,在说跨域方法之前,我们先了解下什么叫跨域,浏览器有同源策略,只有当“协议”、“域名”、“端口号”都相同时,才能称之为是同源,其中有一个不同,即是跨域。
那么同源策略的作用是什么呢?同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
那么我们又为什么需要跨域呢?一是前端和服务器分开部署,接口请求需要跨域,二是我们可能会加载其它网站的页面作为iframe内嵌。
跨域的几种方式
1.jsonp 跨域(优点:简单方便,缺点:只能使用 get 请求,不支持post请求)
3.nginx 的反向代理(少用) apach tomact
4.window.name(少用)
5.axios 反向代理,
6.cors(跨域资源共享)修改服务器端修改包的头部信息,
7.iframe 跨子域(不常用)
8.fetch
jsonp跨域
实现原理:
Step1: 创建 callback 方法
Step2: 插入 script 标签
Step3: 后台接受到请求,解析前端传过去的 callback 方法,返回该方法的调用,并且数据作为参数传入该方法
Step4: 前端执行服务端返回的方法调用
十一、三次握手和四次挥手
SYN 请求
FIN 关闭
ACK 响应
十二、前端的安全 CSRF,XSS,sql 注入
1.sql注入原理:通过sql命令插入到web表单递交或者输入活命,达到欺骗服务器执行的恶意sql命令
防范:
1.对用户输入进行校验
2.不适用动态拼接sql
2.XSS(跨站脚本攻击):往web页面插入恶意的html标签或者js代码。
举例子:在论坛放置一个看是安全的链接,窃取cookie中的用户信息
防范:
1.尽量采用post而不使用get提交表单
2.避免cookie中泄漏用户的隐私
3.CSRF(跨站请求伪装):通过伪装来自受信任用户的请求
举例子:黄轶老师的webapp音乐请求数据就是利用CSRF跨站请求伪装来获取QQ音乐的数据
防范:在客服端页面增加伪随机数,通过验证码
4.XSS和CSRF的区别:
1.XSS是获取信息,不需要提前知道其他用户页面的代码和数据包
2.CSRF代替用户完成指定的动作,需要知道其他页面的代码和数据包
CSRF
跨站请求伪造(Cross—Site Request Forgery),存在巨大的危害性,你可以这样来理解: 攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中 Web A 为存在 CSRF 漏洞的网站,Web B 为攻击者构建的恶意网站,User C 为 Web A 网站的合法用户。
XSS
XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染 DOM 树的过程成发生了不在预期内XSS(Cross Site Scripting),跨站脚本攻击,是一种允许攻击者在另外一个用户的浏览器中执行恶意代码脚本的脚本注入式攻击。本来缩小应该是 CSS,但为了和层叠样式(Cascading Style Sheet,CSS)有所区分,故称 XSS 执行的 JS 代码时,就发生了 XSS 攻击。
SQL 注入
SQL 注入就是一种通过操作输入来修改后台 SQL 语句达到代码执行进行攻击目的的技术。
十三、http
http 协议的理解
1.超文本的传输协议,是用于从万维网服务器超文本传输到本地资源的传输协议
2.基于TCP/IP通信协议来传递数据(HTML,图片资源)
3.基于运用层的面向对象的协议,由于其简洁、快速的方法、适用于分布式超媒体信息系统
4.http请求信息request:
请求行(request line)、请求头部(header),空行和请求数据四部分构成
请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本.
请求头部,用来说明服务器要使用的附加信息
空行,请求头部后面的空行是必须的
请求数据也叫主体,可以添加任意的其他数据。
5.http响应信息Response
状态行、消息报头、空行和响应正文
状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成
消息报头,用来说明客户端要使用的一些附加信息
空行,消息报头后面的空行是必须的
响应正文,服务器返回给客户端的文本信息。
http 和 https 的区别
https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版本,通过SSL加密
http:超文本传输协议。是一个客服端和服务器端请求和应答的标准(tcp),使浏览器更加高效,使网络传输减少
十四、一个页面从url敲入地址到页面显示的全过程
- 浏览器地址栏输入url
- 浏览器会先查看浏览器缓存--系统缓存--路由缓存,如有存在缓存,就直接显示。如果没有,接着第三步
- 域名解析(DNS)获取相应的ip
- 浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手
- 握手成功,浏览器向服务器发送http请求,请求数据包
- 服务器请求数据,将数据返回到浏览器
- 浏览器接收响应,读取页面内容,解析html源码,生成DOm树
- 解析css样式、浏览器渲染,js交互
- 请求页面中需要的js脚本和图片或者样式表
十五、什么是事件代理/事件委托?
事件代理/事件委托是利用事件冒泡的特性,将本应该绑定在多个元素上的事件绑定在他们的祖先元素上,尤其在动态添加子元素的时候,可以非常方便的提高程序性能,减小内存空间。
十六、什么是事件冒泡?什么是事件捕获?
冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
捕获型事件:事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口指定捕获事件,不过必须由开发人员特别指定)。
十七、让元素隐藏有几种方法,及 display:none 和 visibility: hidden 区别 ?
1.display:none 设置元素的 display 为 none 是最常用的隐藏元素的方法。 将元素设置为 display:none 后,元素在页面上将彻底消失,元素本来占有的空间就会被其他元素占有,也就是说它会导致浏览器的重排和重绘。
2.visibility:hidden 设置元素的 visibility 为 hidden 也是一种常用的隐藏元素的方法,和 display:none 的区别在于,元素在页面消失后,其占据的空间依旧会保留着,所以它只会导致浏览器重绘而不会重排。 visibility:hidden 适用于那些元素隐藏后不希望页面布局会发生变化的场景
3.opacity:0 opacity 属性我相信大家都知道表示元素的透明度,而将元素的透明度设置为 0 后,在我们用户眼中,元素也是隐藏的,这算是一种隐藏元素的方法。 这种方法和 visibility:hidden 的一个共同点是元素隐藏后依旧占据着空间,但我们都知道,设置透明度为 0 后,元素只是隐身了,它依旧存在页面中。
4.设置 height,width 等盒模型属性及 font-size 为 0