1 闭包
闭包就是可以访问函数内部变量的函数, 简单理解成"定义在一个函数内部的函数"。
优点:
(1)避免全局污染 局部变量仅在局部作用域内有效
(2)可以用来定义私有属性和私有方法。
缺点: 由于闭包会使得函数中的变量都被保存在内存中、内存消耗很大、不正当使用会造成内存溢出的问题
哪些操作会导致内存泄漏?
(1)意外的全局变量: 无法被回收 (每个浏览器会有自己的一套回收机制,当分配出去的内存不使用的时候便会回收)
// 意外的全局变量 function fn() { a = new Array(10000000); console.log(a); } fn();(2) 没有及时清理的计时器或回调函数
// 没有及时清理的计时器或回调函数var intervalId = setInterval(function () { //启动循环定时器后不清理 console.log('----')}, 1000)// clearInterval(intervalId); //清理定时器(3) 闭包
函数执行完后, 函数内的局部变量没有释放,占用内存时间会变长,容易造成内存泄露。解决方法 能不用闭包就不用,及时释放。<script type="text/javascript"> function fn1() { var arr = new Array[100000]; //这个数组占用了很大的内存空间 function fn2() { console.log(arr.length) } return fn2 } var f = fn1() f() f = null //让内部函数成为垃圾对象-->回收闭包 (当分配出去的内存不使用的时候便会回收)</script>
2 什么是面向对象?
简称 OOP ,是一种编程开发思想,它只是过程式代码的高度封装,目的在于提高代码的开发效率和可维护性
面向对象是以功能来划分问题,而不是步骤
面向对象的特性:
封装性
继承性
[多态性]抽象
对象的创建
//第一种,字面量创建var a={'name':'lala'}; //第二种,构造函数function A(){ this.name='lala';}var a=new A();//第三种,class (ES6标准写法)class A{ constructor(){ //super();此处没有使用extends显式继承,不可使用super() this.name='lala'; }}var a=new A()//其实后面两种方法本质上是一种写法3 继承
子类继承父类,拥有父类的属性和方法,
构造继承
原型继承
组合继承
以下继承的方式核心是在子类的构造函数中通过
Father.call(this)继承父类的属性,然后改变子类的原型为new Father()来继承父类的函数。//组合继承(构造函数+原型继承)//组合式继承是 JS 最常用的继承模式,但组合继承使用过程中会被调用两次:一次是创建子类型的时候,另一次是在子类型构造函数的内部。//定义父构造函数function Father(name,age){ this.name=name; this.age=age;}Father.prototype.eat=function(){ console.log('吃饭');}//定义子构造函数function Son(name,age){ // this指向子构造函数的对象实例 Father.call(this,name,age) }//(错误的)直接指向了父构造函数原型,修改子原型对象 父原型也会跟着改变// Son.prototype=Father.prototype;Son.prototype=new Father();//创建一个父的实例对象,__proto__指向prototype Son.prototype.constructor=Son;// 给子添加考试方法Son.prototype.exam=function(){ console.log('儿子需要考试');}let father=new Father('lisi',50)let son=new Son('zhangsan',30);console.log(father);console.log(son);ES6 class实现继承
class实现继承的核心在于使用extends表明继承自哪个父类,并且在子类构造函数中必须调用super,因为这段代码可以看成Parent.call(this, value)。//其实在 JS中并不存在类,class 只是语法糖,本质还是函数//定义父类class Father{ constructor(name){ this.name=name; }}//定义子类class Son extends Father{ constructor(name,age){ super(name); this.age=age; }}let zs=new Son('zhangsan',18)console.log(zs);
4 原型和原型链
原型:每个构造函数都有prototype属性,这个属性指向原型,
构造函数创建的对象都有一个__proto__属性,这个属性会指向构造函数的prototype原型;
原型链就是多个对象通过 __proto__ 的方式连接起来组成了原型链
当我们访问一个对象的属性时,如果对象内部不存在这个属性,那么他就会去prototype中找,这个prototype又有自己的原型,一直往上找,直到object,这样就形成了一个原型链
function Person() {}var person = new Person();console.log(person.__proto__ === Person.prototype); // true5 如何解决跨域
因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,
Ajax请求会失败。
我们可以通过以下几种常用方法解决跨域的问题
(1) JSONP
JSONP的原理很简单,就是利用<script>标签没有跨域限制的漏洞。通过<script>标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时
<script src="http://domain/api?param1=a¶m2=b&callback=jsonp"></script><script> function jsonp(data) { console.log(data) }</script>
JSONP使用简单且兼容性不错,但是只限于get请求
(2) CORS
ORS需要浏览器和后端同时支持。IE 8和9需要通过XDomainRequest来实现。浏览器会自动进行
CORS通信,实现CORS通信的关键是后端。只要后端实现了CORS,就实现了跨域。服务端设置
Access-Control-Allow-Origin就可以开启CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
jsonp和cors。jsonp是利用 script 标签可以跨域加载的特性而创造出来的一种非正式的跨域解决方案。在实际开发中,推荐使用cors,即在服务端返回时加入允许跨域的请求头,允许指定域名的跨域访问。6 防抖
在持续触发事件的过程中不执行逻辑代码,当触发结束后再执行逻辑代码
//防抖函数function debounce(delay){ let timer=null; return function(){ clearTimeout(timer); timer=setTimeout(()=>{ console.log(1); },delay) }}// 滚动触发window.onscroll=debounce(300);7 节流
在持续触发事件的过程中,每隔一段时间后执行一次,通常使用场景: 滚动条事件 或者 resize 事件,通常每隔 100~500 ms执行一次即可。
8 promise
promise是一种异步编程的解决方案,有三种状态,pending(进行中),resolved(已成功),reject(已失败).
当promise的状态由pending转变为resolved或reject时,会执行相应的方法
9 call, apply, bind
call和apply都是为了解决改变this的指向。作用都是相同的,只是传参的方式不同。除了第一个参数外,
call可以接收一个参数列表,apply只接受一个参数数组bind不会执行对应的函数(call或apply会自动执行对应的函数),而是返回对绑定函数的引用。
let a = { value: 1}function getValue(name, age) { console.log(name) console.log(age) console.log(this.value)}getValue.call(a, 'yck', '24')getValue.apply(a, ['yck', '24'])10 ES6新特性
(1) 增加了let和const命令,用来声明变量
let const:块级作用域、不存在变量提升、不允许重复声明
const: 只读常量 ,无法修改
(2) 解构赋值
从数组和对象中提取值,对变量进行赋值,这被称为解构
以前,为变量赋值,只能直接指定值。
let a = 1;let b = 2;let c = 3;ES6 允许写成下面这样。
let [a, b, c] = [1, 2, 3];(3) 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
(4) 箭头函数(=>)
var f = v => v;// 等同于var f = function (v) { return v;};一、普通函数中this
(1)总是代表着它的直接调用者,谁调用它,它就指向谁
(2)默认情况下,没有直接调用者,this指向window
(3)可以使用call,apply(儿pe赖),bind 改变this指向
二、箭头中this
(1) 箭头函数里面根本没有自己的this,而是引用外层的this
(2)即使是call,apply,bind等方法也不能改变箭头函数this的指向
(3) 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(5)... 扩展运算符
扩展运算符(spread)是三个点(...)。可以讲一个数组或对象 展开
console.log(...[1, 2, 3])// 1 2 3一般用于函数的参数,简化传参的写法(6) Array.from( )
Array.from将类似数组的对象和可遍历的对象转为真正的数组
常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组Array.from(document.querySelectorAll('div'))(7) 数组实例的 find() 和 findIndex()
(1)数组实例的find方法,用于找出第一个符合条件的数组成员(2) findIndex 数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。(8) Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
let s = Symbol();typeof s // "symbol"(9) set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
(10) Promise 对象
https://blog.csdn.net/weixin_42614080/article/details/94711373Promise 是异步编程的一种解决方案,比传统的异步解决方案【回调函数】和【事件】更合理、更强大。现已被 ES6 纳入进规范中。
(11) includes( es7)
(12) 求幂运算符( es7)
(13) async/await (es8)
11 new关键字具体干了什么呢?
(1)开辟内存空间,在内存中创建一个新的空对象。
(2)让 this 指向这个新的对象。
(3)执行构造函数里面的代码,给这个新对象添加属性和方法。
(4)返回这个新对象(所以构造函数里面不需要return)。
12 通过闭包写一个方法,给多个按钮添加点击事件
<button>按钮1</button><button>按钮2</button><button>按钮3</button><script>let btns=document.querySelectorAll('button');for (let i = 0; i < btns.length; i++) { (function(i){ btns[i].onclick=function(){ alert(i); } })(i)}</script>三、Webpack
https://zhuanlan.zhihu.com/p/44438844webpack 是前端模块化打包工具, 帮你打包模块之间的依赖
也可以将es6的语法转为es5 ,将less、sass转为css , .vue转为js
1 webpack打包优化
(1) vue-router路由懒加载
懒加载:也叫延迟加载,即在需要的时候进行加载,随用随载。 使用懒加载的原因: vue是单页面应用,使用webpcak打包后的文件很大,会使进入首页时,加载的资源 过多,页面会出现白屏的情况,不利于用户体验。运用懒加载后,就可以按需加载页面,提高用户体验。
(2) 压缩代码。删除多余的代码、注释、简化代码的写法等等方式。
可以利用webpack的UglifyJsPlugin来压缩JS文件
(3) 利用 CDN 加速。在构建过程中,将引用的静态资源路径修改为 CDN 上对应的路径
2 什么是模块热更新:
模块热更新是webpack的一个功能,他可以使得代码修改过后不用刷新浏览器就可以更新,是高级版的自动刷新浏览器(将代码重新执行而不整体刷新浏览器)3 几个常见的plugin和常见的loade
(1)plugin: html-webpack-plugin 为html文件中引入的外部资源,可以生成创建html入口文件 mini-css-extract-plugin 分离css文件 clean-webpack-plugin 删除打包文件 HotModuleReplacementPlugin 热更新应用 copy-webpack-plugin 拷贝静态文件 terser-webpack-plugin 通过TerserPlugin压缩ES6代码
(2) loader:
uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码
css-loader 加载 CSS,支持模块化、压缩、文件导入等特性 image-loader 加载并且压缩图片文件 babel-loader 把 ES6 转换成 ES5 style-loader 把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS file-loader 把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
三 git
(1) 工作中常用的git命名
git add . 添加当前目录的所有文件到暂存区
git commit -m 提交暂存区的指定文件到本地仓库
git status 查看状态
git push 上传
git pull 拉取
git clone 克隆
git branch 分支名 // 新建分支
git branch // 查看当前所有分支
git checkout 分支名 // 切换分支
git checkout -b 分支名 // 创建并切换分支
git merge 分支名 // 把该分支的内容合并到现有分支上
(2) 提交冲突 如何解决
冲突原因: 远程仓库中的内容与本地不一致
通过git pull命令,拉取远程分支上的代码并合并到本地分支,消除冲突;