一、.什么是原型,什么是原型链?以及原型对象的constructor
属性
《JavaScript教程-网道》
https://wangdoc.com/javascript/oop/prototype.html
1.原型
原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。
JavaScript 规定,每个函数都有一个prototype
属性,指向一个对象。
对于普通函数来说,该属性基本无用。但是,对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型。
原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。
当实例对象本身没有某个属性或方法的时候,它会到原型对象去寻找该属性或方法。这就是原型对象的特殊之处。
如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。
总结一下,原型对象的作用,就是定义所有实例对象共享的属性和方法。这也是它被称为原型对象的原因,而实例对象可以视作从原型对象衍生出来的子对象。
《廖雪峰JavaScript》
JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。
2.原型链
原型链的基本概念
将父类型的实例作为子类型的原型对象,以此构成的链式关系叫做原型链。
https://blog.csdn.net/qq_35732147/article/details/82801533
JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype
,即Object
构造函数的prototype
属性。也就是说,所有对象都继承了Object.prototype
的属性。这就是所有对象都有valueOf
和toString
方法的原因,因为这是从Object.prototype
继承的。
那么,Object.prototype
对象有没有它的原型呢?回答是Object.prototype
的原型是null
。null
没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null
。
3.原型对象的constructor
属性
prototype
对象有一个constructor
属性,默认指向prototype
对象所在的构造函数。
constructor
属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。
另一方面,有了constructor
属性,就可以从一个实例对象新建另一个实例。
constructor
属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor
属性,防止引用的时候出错。
修改原型对象时,一般要同时修改constructor
属性的指向。
二、继承
ES5通过修改原型链实现继承
ES6中Class 可以通过extends
关键字实现继承
1.基于对象的继承
使用Object.create(),直接让新对象继承旧对象的属性
https://www.cnblogs.com/libinfs/archive/2017/11/23/7885337.html
2.基于构造函数的继承
https://wangdoc.com/javascript/oop/prototype.html
举例来说,下面是一个Shape
构造函数
1 function Shape() { 2 this.x = 0; 3 this.y = 0; 4 } 5 6 Shape.prototype.move = function (x, y) { 7 this.x += x; 8 this.y += y; 9 console.info('Shape moved.'); 10 };
我们需要让Rectangle
构造函数继承Shape
。
1 // 第一步,子类继承父类的实例 2 function Rectangle() { 3 Shape.call(this); // 调用父类构造函数 4 } 5 // 另一种写法 6 function Rectangle() { 7 this.base = Shape; 8 this.base(); 9 } 10 11 // 第二步,子类继承父类的原型 12 Rectangle.prototype = Object.create(Shape.prototype); 13 Rectangle.prototype.constructor = Rectangle;
- 每一个对象自身都拥有一个隐式的
[[proto]]
属性,该属性默认是一个指向其构造函数原型属性的指针; - 几乎所有函数都拥有
prototype
原型属性;
我们设置一个对象的继承关系,本质上是在操作对象隐式的[[proto]]
属性
关于构造函数、原型属性、实例对象的理解
1 // 构造函数、原型属性、实例对象 2 3 // 构造函数(它用来“构造”对象,并且是一个函数) 4 function Person(name, age) { 5 var gender = girl // ①构造函数的私有属性 6 this.name = name // ②构造函数的自有属性 7 this.age = age 8 } 9 10 // ③Person.prototype是Person的原型对象,是实例对象的原型,是一个对象 11 // 是构造函数的原型属性,该对象上的所有属性(和方法)都会被实例对象所继承 12 Person.prototype.sayName = function() { 13 alert(this.name) 14 } 15 // ④构造函数Person的实例对象,它可以访问到两种属性 16 // ,一种是通过构造函数生成的“自有属性”, 17 // 一种是原型对象可以访问的所有属性; 18 var kitty = new Person('kitty', 14) 19 20 kitty.sayName() // kitty
在JavaScript世界,实现继承的方式有以下两种:
- 创建一个对象并指定其继承对象(原型对象);
- 修改构造函数的原型属性(对象);
通过修改[[proto]]
属性的值,我们就能决定对象所继承的对象,从而以我们想要的方式实现继承。
方式一:关于Object.create()
和对象继承
Object.create()
函数是JavaScript提供给我们的一个在创建对象时设置对象内部[[proto]]
属性的API,Object.create()
函数接收两个参数,第一个参数是创建对象想要继承的原型对象,第二个参数是一个属性描述对象
1 var x = { 2 name: 'tom', 3 sayName: function() { 4 console.log(this.name) 5 } 6 } 7 var y = Object.create(x, { 8 name: { 9 configurable: true, 10 enumerable: true, 11 value: 'kitty', 12 writable: true, 13 } 14 }) 15 y.sayName() // 'kitty'
调用Object.create()
时究竟发生了什么:
- 创建了一个空对象,并赋值给相应变量;
- 将第一个参数对象设置为该对象
[[proto]]
属性的值; - 在该对象上调用
defineProperty()
方法,并将第二个参数传入该方法中;
方式二:关于prototype 和构造函数继承
构造函数生产实例对象的过程本身就是一种天然的继承,实例对象天然的继承着原型对象的所有属性,这其实是JavaScript提供给开发者第二种(也是默认的)设置对象[[proto]]
属性的方法。
https://wangdoc.com/javascript/oop/prototype.html
1)构造函数的继承
让一个构造函数继承另一个构造函数,是非常常见的需求。这可以分成两步实现。
第一步是在子类的构造函数中,调用父类的构造函数。
第二步,是让子类的原型指向父类的原型,这样子类就可以继承父类原型。
三、vue的双向数据绑定
1)v-model 指令实现数据双向绑定
v-model 指令实现数据从M 渲染到V,也能实现V里面数据改变同步到M里面去
使用 v-model 指令,可以实现 表单元素 和 Model 中数据的双向数据绑定 注意:v-model 只能运用在 表单元素中 常见的表单元素: input(radio,text,address,email......) select checkbox textarea
2)双向绑定从本质上来说无非两部分 Model->View 与 View->Model
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="utf-8"> 6 <meta name="viewport" content="width=device-width,initial-scale=1.0"> 7 <title>Document</title> 8 <!--1.导入Vue的包--> 9 <script src=" https://cdn.jsdelivr.net/npm/vue"></script> 10 </head> 11 12 <body> 13 <div id="app"> 14 <h4>{{msg}}</h4> 15 <!-- v-bind只能实现数据的单向绑定,从M 自动绑定到 V,无法实现数据的双向绑定 --> 16 <!-- <input type="text" v-bind:value="msg" style="width: 100%"> --> 17 18 <!-- 使用 v-model 指令,可以实现 表单元素 和 Model 中数据的双向数据绑定 --> 19 <!-- 注意:v-model 只能运用在 表单元素中 --> 20 <!-- 常见的表单元素: input(radio,text,address,email......) select checkbox textarea --> 21 <input type="text" value="msg" style="width: 100%;" v-model="msg"> 22 </div> 23 24 25 <script> 26 // 创建 Vue 实例,得到 ViewModel 27 var vm = new Vue({ 28 el:'#app', 29 data:{ 30 msg:'我爱前端!' 31 }, 32 methods:{} 33 }); 34 </script> 35 </body> 36 </html>
四、cookie、session、localStorage、sessionStorage之间的不同
1.什么是Cookie?
Cookie 是一些数据, 存储于你电脑上的文本文件中。
当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息。
Cookie 的作用就是用于解决 "如何记录客户端的用户信息":
- 当用户访问 web 页面时,他的名字可以记录在 cookie 中。
- 在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。
2.Session
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。
3.localStorage 和 sessionStorage 属性
localStorage 和 sessionStorage 属性允许在浏览器中存储 key/value 对的数据。
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。localStorage 属性是只读的。(localStorage也是Storage类型的一个对象。)
sessionStorage 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。(sessionStorage是Storage类型的一个对象)
https://www.runoob.com/jsref/prop-win-localstorage.html
https://www.kancloud.cn/xiaoxiaoqc/web/137937
五、深浅拷贝
原文地址:
https://juejin.im/post/5b00e85af265da0b7d0ba63f
https://www.cnblogs.com/136asdxxl/p/8645750.html
ECMAScript中不同数据类型的复制方式
- 基本类型:从一个变量向另外一个新变量复制基本类型的值,会创建这个值的一个副本,并将该副本复制给新变量
- 引用类型:从一个变量向另一个新变量复制引用类型的值,其实复制的是指针,最终两个变量最终都指向同一个对象
深拷贝 & 浅拷贝
- 浅拷贝:仅仅是复制了引用,彼此之间的操作会互相影响
- 深拷贝:在堆中重新分配内存,不同的地址,相同的值,互不影响
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
浅拷贝:
1.concat() 方法用于连接两个或多个数组
arrayObject.concat(arrayX,arrayX,......,arrayX)
2.slice() 方法可从已有的数组中返回选定的元素
arrayObject.slice(start,end)
深拷贝:
- JSON.stringify():把一个js对象序列化为一个JSON字符串
- JSON.parse():把JSON字符串反序列化为一个js对象
JSON.parse()和JSON.stringify()是完全的深拷贝。
六、事件委托冒泡
可参考这篇博客:https://www.cnblogs.com/soyxiaobi/p/9498357.html
事件委托的优点:
-
- 提高性能:每一个函数都会占用内存空间,只需添加一个事件处理程序代理所有事件,所占用的内存空间更少。
- 动态监听:使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以一样具有和其他元素一样的事件。
1 <script> 2 window.onload = function(){ 3 let div = document.getElementById('div'); 4 5 div.addEventListener('click',function(e){ 6 console.log(e.target) 7 }) 8 9 let div3 = document.createElement('div'); 10 div3.setAttribute('class','div3') 11 div3.innerHTML = 'div3'; 12 div.appendChild(div3) 13 } 14 </script> 15 16 17 <body> 18 <div id="div"> 19 <div class="div1">div1</div> 20 <div class="div2">div2</div> 21 </div> 22 </body>
虽然没有给div1和div2添加点击事件,但是无论是点击div1还是div2,都会打印当前节点。因为其父级绑定了点击事件,点击div1后冒泡上去的时候,执行父级的事件。
以下是关于事件的基础知识:
1)事件是文档或浏览器窗口中发生的特定的交互瞬间。
JavaScript和HTML之间的交互是通过事件实现的。
2)事件流——描述的是从页面中接受事件的顺序
IE——事件冒泡流
Netscape——事件捕获流
3)事件冒泡:即事件最开始由最具体的元素(文档中嵌套层次最深的哪个节点)接收,然后逐级向上传播至最不具体的哪个节点(文档)。
click事件在input触发,它会一级一级往上冒,直到冒到document上
点击按钮不但触发了按钮,也触发了div、body直到document
4)事件捕获:不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。
事件接收顺序:window对象->document->html->body->div->input
七、闭包
闭包就是能够读取其他函数内部变量的函数。
1 function f1() { 2 var n = 999; 3 function f2() { 4 console.log(n); 5 } 6 return f2; 7 } 8 9 var result = f1(); 10 result(); // 999
这里的闭包就是函数f2。
闭包的作用:
- 可以读取函数内部的变量
- 让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。
- 封装对象的私有属性和私有方法
注意,外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。
八、继承
1.原型
JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。
当我们用obj.xxx
访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype
对象,最后,如果还没有找到,就只能返回undefined
。
九、设计模式
原文参考:https://juejin.im/post/59df4f74f265da430f311909
设计模式的通俗解释:设计模式是解决某个特定场景下对某种问题的解决方案。
1.单例模式
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2.策略模式
策略模式的定义:定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。
策略模式的目的就是将算法的使用算法的实现分离开来。
3.代理模式
代理模式的定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。
常用的虚拟代理形式:某一个花销很大的操作,可以通过虚拟代理的方式延迟到这种需要它的时候才去创建(例:使用虚拟代理实现图片懒加载)
图片懒加载的方式:先通过
一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。
4.中介者模式
中介者模式的定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
中介者模式适用的场景:例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
5.装饰者模式
装饰者模式的定义:在不改变对象自身的基础上,在程序运行期间给对象动态地添加方法。
装饰者模式适用的场景:原有方法维持不变,在原有方法上再挂载其他方法来满足现有需求;函数的解耦,将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。
前端面经
招银电面前端
链接:https://www.nowcoder.com/discuss/287857?type=all&order=time&pos=&page=0
1.自我介绍
2.说下自己的项目
3.vue的双向数据绑定
4.深浅拷贝
5.事件委托冒泡
6.闭包
7.继承
8.原型链
9.设计模式
去哪儿前端
链接:https://www.nowcoder.com/discuss/275111?type=all&order=time&pos=&page=1
链接: https://www.nowcoder.com/discuss/274734?type=all&order=time&pos=&page=1
4399
1.自我介绍
2.http与https https一定比http好吗
3.es6新特性
4.promise proxy
5.闭包
6.深拷贝与浅拷贝
7.三百万个数 用算法取前十个
反正问的挺多的 其他的不记得了 看重基础
海康
1.自我介绍
2.js比其他语言好在哪里
3.js增删改差
4.nodejs
5.css左边固定右边自适应