只看不练习,注重基础练习(听懂+大量练习 = 学会)
多做笔记+思维导图(多沉淀+不能只做流水+写出自己的理解)
背语法规则,其他要理解原理,不能死记硬背(比如说数据结构、底层原理、优化等等)
不要纠结记不住算法,报错要积极调错不能逃避才能提高,反了足够的错误就是高手了
不能闭门造车,找学习、高手;不想学习就确定一个高手或者搞定一本书
不能只是疲于奔命,什么都学,什么都不精通,没有建立真正的体系;
明确方向和目标,确定每个阶段,以及完成情况,要抓紧落实
只专注看一本书或者一个视频,其他的只作为某个知识点的补充和参考
重要的五种题型
js基本数据类型
Number、String 、Boolean 、Null、Undefined、Symbol(新类型,表示全局唯一)
数据封装类对象:Object、Array、Boolean、Number 和 String
其他对象:Function、Arguments、Math、Date、RegExp、Error
谈谈对this的理解
另外,this的绑定规则
eval是做什么的
它可以把字符串转化为对应的JavaScript代码并运行;尽量避免使用,不安全且耗能(2次,解析、执行)
javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?
除了正常模式运行外,ECMAscript添加了第二种运行模式:“严格模式”。
作用:
对箭头函数有什么了解
箭头函数是es6里面新加的,表示方法比传统创建函数对象的方法更加简洁。但是箭头函数不能使用argument、super、new.target、不绑定this,没有prototype属性,也不能使用构造函数。
如何判断数组
最高级的实现:polyfill
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
const arr = [1, 2, 3, 4]
Object.prototype.toString.call(arr) === '[Object Array]' // true
instanceof原理
概念:instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象原型链中的任何位置
即:若A instanceof B表示判断 B 的 prototype 属性指向的原型对象(B.prototype)是否在对象 A 的原型链上。
如何判断属性是对象实例中的属性还是原型中的属性
ECMAScript5中的hasOwnProperty()方法,用于判断只在属性存在与对象实例中的时候,返回true,in操作符只要通过对象能访问到属性就返回true。
因此只要in操作符返回true而hasOwnProperty()返回false,就可以确定属性是原型中的属性。
所以有如下函数:
···js
function hasPrototypeProperty(obj, name) {
return !obj.hasOwnProperty(name) && (name in obj);
}
···
es6的模块化和commenjs模块化区别和差异
模块化就是将变量和函数 放入不同的文件中,减少全局变量 避免变量名和函数命名冲突,提高代码的复用性和维护性 。
①表达方式的不同es6 export import commonhjs module.export require
②注意点:commonJs值的拷贝,es6值的引用、只能放在顶层作用域
③common异步加载、es是同步加载
④commonJS运行时加载,es6编译时输出接口
es6的模块化和commenjs模块化区别
Promise 的优缺点
缺点:
无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
如果不设置回调函数,promise 内部抛出的错误,不会反应到外部。
当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
优点:
解决回调地狱(Callback Hell)问题
代码更扁平,可读性更高
更好地进行错误捕获
CSS有哪些字体单位?
js发展历史
JS的历史
原生JS操作 → DOM节点
Jquery 快速操作DOM的工具集,与浏览器更加兼容
Vue/React/angular 真实DOM和VDOM进行同步
已经不是DOM驱动了,而是数据驱动了,我们只需要去关注我们的数据和我们的业务逻辑。
获取DOM的话操作会更加灵活一些
前端工程化
前端渲染 vs 后端渲染
单页面/多页面的描述其实是不太准确的
html + css + 数据 在哪里结合很关键
html + 数据 → 服务端|服务端渲染|要有模板引擎去做html和数据的结合|最终返回的是html
html (css + js) Vue来与服务端通信,然后来进行数据渲染
数据|通过js加载 + API ⇒ 浏览器渲染的过程
所以其实不是单页面/多页面的问题而是数据在哪里渲染的问题
单页面/多页面只是说大多数场景下是这样而已
其实现在前后端是 两个应用程序之间的通信。
大部分的数据服务端渲染,少部分动态的数据浏览器渲染也是可行!ajax
大型架构的话还是以服务端渲染为主。浏览器渲染有个致命缺陷就是seo的不支持。
传统网站是不太适合用框架开发的。框架更适合去开发cms|还有就是APP里面的内置H5.
nuxt.js 对框架来进行服务端渲染,有优化的成本很高了
但这个传统的web+模版引擎已经有很多性能优化的方案了。
比如:不经常改变的html放在CDN里
2021-3-9
js基本数据类型和引用数据类型,判断基本数据类型的几种方式
js作用域(全局作用域和函数作用域);var、let、const区别;JS原型链与instanceof底层原理,for-in【索引】和for-of区别【值】;
const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。for-in for-of遍历数组和遍历对象的结果不一样
数组:for-in 遍历的是键名(索引); for-of遍历的是value值
对象:for-in 遍历的是键名 ;
for-in 更适合遍历对象,,for-of不能遍历对象
原因用for-in遍历的话:
遍历顺序有可能不是按照实际数组的内部顺序
index索引为字符串型数字,不能直接进行几何运算
使用for in会遍历数组所有的可枚举属性
原型方法method和name属性
上面的in与下面这句console.log("name" in mc);
的意义不一样,这里in检查mc对象里面是否含有name属性,如果对象中没有而原型中有的话也会返回true
原型链
js对象有一个对象.prototype属性,prototype属性内有__proto__指向其父类,父类再用__proto__指向它的父类,直到指向Object原型方法内的proto属性为空,这样就形成了原型指向的链条叫原型链
另外prototype属性内还有一个constructor方法,这个方法指向所属类
ES5 和 ES6 分别几种方式声明变量
ES5 有俩种:var
和 function
ES6 有六种:增加四种,let
、const
、class
和 import
注意:let
、const
、class
声明的全局变量再也不会和全局对象的属性挂钩
闭包的概念?优缺点?
内嵌函数,函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。并且函数B内变量暂时不会被销毁
(简单理解为闭包就是能读取其他函数内部变量的函数。)
优点:避免全局变量的污染、私有属性;希望一个变量长期存储在内存中
缺点:内存泄露;常驻内存,增加内存使用量
应用:
var obj = {
name: 'tom',
sayName() {
var name = 'alan';
console.log(this.name);
}
}
obj.sayName();// 'tom'
var name = 'jerry';
var obj = {
name : 'tom',
sayName(){
return function(){
console.log(this.name);
};
}
};
obj.sayName()(); // jerry
JavaScript垃圾回收机制
定义:指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束
像 C 这样的编程语言,具有低级内存管理原语,如 malloc()和 free()。开发人员使用这些原语显式地对操作系统的内存进行分配和释放。
而 JavaScript 在创建对象(对象、字符串等)时会为它们分配内存,不再使用对时会“自动”释放内存,这个过程称为垃圾收集。
内存生命周期中的每一个阶段:
分配内存 — 内存是由操作系统分配的,它允许您的程序使用它。在低级语言(例如 C 语言)中,这是一个开发人员需要自己处理的显式执行的操作。然而,在高级语言中,系统会自动为你分配内在。
使用内存 — 这是程序实际使用之前分配的内存,在代码中使用分配的变量时,就会发生读和写操作。
释放内存 — 释放所有不再使用的内存,使之成为自由内存,并可以被重利用。与分配内存操作一样,这一操作在低级语言中也是需要显式地执行。
对前端性能优化有什么了解?一般都通过那几个方面去优化的?
``前端性能优化的七大手段`
赋值、浅拷贝与深拷贝?
复制// 第一层为深拷贝
Object.assign()
Array.prototype.slice()
扩展运算符 ...
复制JSON.parse(JSON.stringify())
递归函数
复制function cloneObject(obj) {
var newObj = {} //如果不是引用类型,直接返回
if (typeof obj !== 'object') {
return obj
}
//如果是引用类型,遍历属性
else {
for (var attr in obj) {
//如果某个属性还是引用类型,递归调用
newObj[attr] = cloneObject(obj[attr])
}
}
return newObj
}
2021-3-11
有以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣 【具体点开跳转文章查看】
Object.prototype.toString.call() 、 instanceof 以及 Array.isArray()
// 4种判断是否是数组的方式:
Array.isArray(arr)
arr instanceof Array
arr.constructor === Array
Object.prototype.toString.call(arr) === '[object Array]'
...
‘https://www.cnblogs.com/onepixel/p/5126046.html’
怎么理解原型链
js对象有一个对象.prototype属性,prototype属性内有__proto__指向其父类,父类再用__proto__指向它的父类,直到指向Object原型方法内的proto属性为空,这样就形成了原型指向的链条叫原型链
另外prototype属性内还有一个constructor方法,这个方法指向所属类
async/await 的详解
(1) 内置执行器
Generator 函数的执行必须靠执行器,所以才有了co模块。
Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。
async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
自动执行,输出最后结果
(2)更好的语义。
(3)适用性广
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象
await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
(4)async函数的返回值是 Promise 对象
function stop_buble(e) {
let ev = e || window.event
if (ev && ev.stopProgation) {
ev.stopProgation()
} else {
ev.cancelBubble()
}
}
script标签中defer和async的区别是什么?
默认下载和执行脚本将会按照文档的先后顺序同步进行。当脚本下载和执行的时候,文档解析就会被阻塞,在脚本下载和执行完成之后文档才能往下继续进行解析。
下面是async和defer两者区别:
- 当script中有defer属性时,脚本的加载过程和文档加载是异步发生的,等到文档解析完,脚本才开始执行。
- 当script有async属性时,脚本的加载过程和文档加载也是异步发生的。停止HTML解析,先脚本解析完再继续HTML解析。
- 当script同时有async和defer属性时,取async
wait发生异常还能不能解析往下执行?
如果有错误发生 使用try catch 捕获异常
描述一下 V8 执行一段JS代码的过程
词法分析和语法分析成ast(语法抽象树)
ast -> 解释器 -> 字节码
执行字节码,编译器将字节码逐行转换成机器码。执行的过程中如果有热点代码就不会再将热点代码转换为机器码,而是直接使用之前保存好的机器码
其中,
字节码是介于AST 和 机器码之间的一种代码
热点代码:js语句转换的字节码中相同的代码就叫热点代码。
栈和堆分别是什么?
栈——先进后出、
堆——优先队列,可以根据文件大小进行排列,完全二叉树是其中的一种实现方式
栈——编译器自动分配释放,存储参数值或局部变量的值
堆:由程序员手动释放或垃圾回收机制释放
undefined 和 undeclared的区别
undefined 声明未赋值,undeclared未声明
shijxh
js的指向问题
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this永远指向最后调用它的那个对象。
如果有new关键字,this指向new出来的那个对象
其中,箭头函数的this始终指向函数定义时的this,而非执行时。箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值。
apply、call、bind的区别
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.apply(a,[1,2]) // 3
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.call(a,1,2) // 3
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.bind(a,1,2)() // 3
2021-3-20
ES5和ES6继承的区别
ES5先创建子类的实例对象,再将父类添加到子类的原型链上 Parent.apply(this)
ES6先创建父类的实例对象,子类通过extend关键字继承父类的属性和方法
具体的:ES6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其进行加工。如果不调用super方法,子类得不到this对象。