JavaScript 基础篇

134 阅读7分钟

Js 由哪三部分组成

ECMAScript(JS的核心内容,描述了语言的基础语法,比如var、for、数据类型(数组、字符串等)),

文档对象模型(DOM):DOM把整个HTML页面规划为元素构成的文档

浏览器对象模型(BOM)把浏览器窗口进行访问和操作

script标签里的async 和defer有什么区别

当没有async 和defer 这两个属性的时候,浏览器会立刻加载并执行指定的脚本,

有async 加载和渲染后面元素的过程将和script 的加载和执行并行进行(异步)

有defer 加载和渲染后面元素的过程将和script的加载并行进行(异步),但是它的执行事件要等所有元素解析完成之后才会执行,

延迟加载 async 、 defer

defer:等html 全部解析完成,才会执行js代码,顺序执行js脚本

Async:async是和html解析同步的(一起的),不是顺序执行js脚本(谁先加载完谁先执行)

前端内存泄漏怎么理解

JS里已经分配内存地址的对象,但是由于长时间没有释放或者没办法清除,造成长期占用内存的现象,会让内存资源大幅浪费,最终导致运行速度慢,甚至崩溃的情况。

垃圾回收机制

因素:一些为生命直接赋值的变量:一些为清空的定时器,过渡的闭包,一些引用元素没有清除

说一下事件循环

JS是一个单线程的脚本语言,主线程先执行同步任务,然后才去执行任务队列里的任务,如果在执行宏任务之前有微任务,那么先执行微任务,全部执行完之后等待主线程的调用,调用完之后再去任务队列中查看是否有异步任务,这样一个循环往复的过程就是事件循环!

事件委托是什么

又叫事件代理,原理就是利用了事件冒泡的机制来实现的,也就是说把子元素的事件绑定到了父元素的身上,如果子元素阻止了事件冒泡,那么委托也就不成立

阻止事件冒泡:event.stopPropagation(),addEventListener(‘click’,函数名,true/false) 默认是false (事件冒泡),true(事件捕获)

好处:提高性能,减少事件的绑定,也就减少了内存的占用。

Svg格式了解多少

基于XML语法格式的图像格式,可缩放矢量图,其他图像是基于像素的,SVG是属于对图像形状的描述,本质是文本文件,体积小,并且不管放大多少倍都不会失真

1.SVG可直接插入页面中,成为DOM一部分,然后用JS或CSS进行操作<svg></svg>

2.SVG可作为文件被引入<img src=“”pic.svg />

3.SVG可以转为base64引入页面

setTimeout最小执行时间是多长

HTML5的规定的内容

setTimeout 最小执行时间是4ms,setInterval最小执行时间是10ms

DOM事件的注册和移除

// 内联事件
<button onclick = "onClick('wangjianguo')">按钮</button>

function onClick(param){
    console.log(`你点击了按钮,${param}`)
}

// 通过HTML DOM 设置
var button = document.getElementById('myButton')
button.onClick = function() {
    console.log("点击了事件1")
}
button.onClick = function() {
    console.log("点击了事件2")
}
// 移除事件处理器
button.onClick = null

// 添加事件监听器
var button = document.getElementById("myButton")
button.addEventListener = function() {
    console.log("点击了事件1")
}
button.addEventListener = function() {
    console.log("点击了事件2")
}
// 移除事件处理器
button.removeEventListener('click',myFunction)

// 兼容老版本IE浏览器
// button.attachEvent('onClick',myFunction)

什么是属性描述符

6种属性描述符

  • value:设置属性值,默认值为undefined.
  • writable:设置属性值是否能被修改,默认值为true
  • enumerable:设置属性是否可枚举。比如:是否允许使用for/in 语句遍历访问,默认为true
  • configurable:控制的是属性的配置,包括是否可以更改属性描述符,以及是否可以从对象中删除属性。
  • get:取值函数,当访问该属性时,该方法会被执行,默认为undefined
  • set:存值函数,当属性值修改时,触发执行该方法,默认为undefined

属性描述符configureable 和 writable

var obj = {} // 定义空对象
Object.defineProperty(obj,"age",{
    value:18,
    writable:false // 禁止修改属性值
})
obj.age = 28 // 由于禁止修改,此时修改失败
console.log(obj.age) // 结果仍难是18
console.log(Object.getOwnPropertyDescriptor(obj,"age").value)//18
var obj = {} // 定义空对象
Object.defineProperty(obj,"age",{
    writable:true 
    configureable:false // 禁止配置(换而言之,无法修改属性描述符)
})
obj.age = 28
console.log(obj.age) //28
console.log(Object.getOwnPropertyDescriptor(obj,"age").value)//28

// 修改属性描述符
Object.definedProperty(obj,"age",{value:2}) // 抛出异常
Object.definedProperty(obj,"age",{writable:true}) // 抛出异常
Object.definedProperty(obj,"age",{enumerable:true}) // 抛出异常
Object.definedProperty(obj,"age",{configureable:true}) // 抛出异常

属性描述符get和set应用

var obj = Object.create(Object.prototype,{
    _age:{
        value:18,
        writable:true
    },
    age:{
        get:function(){
            return this._age
        },
        set:function(){
            this._age = value
        }
    }
})
console.log(obj.age) // 18
obj.age = "28"
console.log(obj.age) // 28

enumerable

var person = {
   name:'wangjianguo',
   age:30,
   gender:"male"
}
for (var key in person) {
    console.log(key + ":" + person[key])
    /*打印 
      name:'wangjianguo',
      age:30,
      gender:"male"
    */ 
}
var obj = {}

Object.defineProperty(obj,"visibleProperty",{
    value:"我是可枚举的",
    enumerable:true,
})
Object.defineProperty(obj,"hiddenProperty",{
    value:"我是不可枚举的",
    enumerable:false,
})

console.log(Object.keys(obj)) // ['visibleProperty']
console.log(Object.getOwnPropertyNames(obj))

如何操作属性描述符

什么是柯里化 将使用多个参数的函数转换为一系列使用一个参数的函数

parseInt与Math.floor使用场景对比

相同点 都能获取小数的整数部分

console.log(Math.floor(4.95)) // 4
console.log(parseInt(4.95)) // 4

Math.floor 无论正负,Math.floor 都是简单地将一个数向下取整到最接近的整数。

console.log(Math.floor(4.95)) // 4
console.log(Math.floor(4.5)) // 4
console.log(Math.floor(4.05)) // 4
console.log(Math.floor(-4.05)) // -5

parseInt的特点

对于负数,会向上取整到最接近的整数

对于正数,会向下取整到最接近的整数

console.log(Math.floor(-4.05)) // -5
console.log(parseInt(-4.05)) // -4

parseInt的其他特点 parseInt会忽略任何数字后面的非数字字符

console.log(Math.floor('4.05abc')) // 4
console.log(parseInt("4.05abc")) // NaN

parseInt处理不同的进制数据:

parseInt("11",2) 
// 结果是3 因为在2进制中,11表示的是十进制中的3

手写实现数组扁平化

遍历数组,如果每一项还是一个数组,那么就继续往下遍历,利用递归的方法

Array.prototype.customFlatten = function(){
    //转化结果
    let flat = []
    for (let item of this) {
        if (Array.isArray(item)){
            flat = flat.concat(item.customFlatten())
        }else {
            flat.push(item)
        }
    }
    return flat
}

let arr =[
    [1,2,9],[2,3,3,3],[3,4,5,[6,6,7,8]]
]
//输出 [1,2,9,2,3,3,3,3,4,5,6,6,7,8]
console.log(arr.customFlatten())

不使用临时变量temp 交换x和y的值

临时变量temp

// 临时变量temp
let x = 1
let y = 2

let temp = x
x = y
y = temp
console.log(x,y)

ES6 解构操作

// ES6 解构操作
let x = 1
let y = 2

[y,x] = [x,y]
console.log(x,y)

异或

//异或
let x = 1
let y = 2

x = x ^ y
y = x ^ y
x = x ^ y
console.log(x,y)

加减运算

//加减运算
let x = 1
let y = 2

x = x + y // 原来两数之和
y = x - y // 两数之和 - y
x = x - y // 两数之和 - x
console.log(x,y)

自增运算符

i++ 先返回i的值,再执行i的自增运算

++i 先对i自增运算,再返回修改后的值

let i = 1
console.log(i++ + ++i) // 4
console.log(i++ + ++i * ++i) // 13

function函数length属性

第一个有默认值之前的参数,不考虑剩余参数。没有默认值的参数,那就全部是

function fun1(a){}
function fun2(b = 'a',a){}
function fun3(a,b = 'a'){}
//...arr 不考虑剩余参数
function fun3(a,...arr){}

console.log(fun1.length) // 1
console.log(fun2.length) // 0
console.log(fun3.length) // 1
console.log(fun4.length) // 1

动态执行,动态执行方式

方法一:使用eval()函数

// 方式1,传给eval函数,把字符串当成代码执行
let code = "console.log("hello Word")"
eval(code)

// 方式2,平时使用settimeout 是传一个回调函数,setTimeout(() => {},0)

setTimeout(code,0)

// 方式3
let x = 1
var script = document.createElement("script")
scipt.textContent = code
document.body.appendChild(script)

方法二:使用settimout()函数

方法三:添加新的<script>标签

动态属性和静态属性

静态属性访问:

  1. 通过点符号(.)访问的属性是静态的。
  2. 属姓名是硬编码,且在编写代码时就已知。
  3. 不能使用变量作为属姓名
var person = {
    prop:"wangjianguo"
}

function test(){
    console.log(person.prop)
}

动态属性访问

  1. 通过方括号访问的属性是动态的。
  2. 属性名可以在运行时计算得出的。我们可以使用变量、字符串字面量或表达式
var person = {
    a:'wangjianguo',
    b:'hello,word'
}

var prop = 'a'
setTimeout(() =>{
    prop = 'b'
},2000)

function test(){
    console.log(person.prop)
}

纯函数

确定性:对于相同呢大的输入,纯函数总是产生相同的输出。 无副作用:纯函数不会修改其外部环境,包括全局变量、输入参数对象等。

纯函数

function add(a ,b){
    return a + b
}

不是纯函数,修改了外部变量

let globalVar = 0
function add(a,b){
    globalVar += 1
    return a + b + globalVar
}

JavaScript提供了哪些纯函数

toSorted()

let arr = [5,1,9]
// 返回新数组,没有改变原数组
let newArr = arr.toSorted();
console.log(newArr)

toReversed()

反转数组

let reveredArr = arr.toReversed()

toSpliced()

删除数组元素

let splicedArr = arr.toSpliced()

with()

修改数组元素

let newArr = arr.with(0,1)

属性私有化

nuxt.js

是基于vue的应用框架,关注的是渲染,可以开发服务端渲染应用的配置

SSR:服务端渲染

好处:

SSR生成的是有内容的HTML页面,有利于搜索引擎的搜索

优化了首屏加载时间

SEO:优化搜索引擎

SPA的应用不利于搜索引擎SEO的操作

SEO如何优化

  1. SSR
  2. 预渲染 prerender-spa-plugin

如何封装组件

组件一定要难点,涉及的知识点;插插、组件通信。。。

Vue3的性能为什么比vue2好

  1. diff算法的优化
  2. 静态提升
  3. 事件侦听缓存

Vue的性能优化怎么做

1.编码优化

不要把所有数据都放在data中

v-for时给每个元素绑定事件用事件代理

keep-alive缓存组件

尽可能拆分组件,提高复用性,维护性

key值要保证唯一

合理使用路由懒加载,异步组件

数据持久化存储的使用尽量用防抖、截流优化

2.加载优化

按需加载

内容懒加载

图片懒加载

3.用户体验

骨架屏

4.SEO优化

预渲染

服务端渲染SSR

5.打包优化

CDN形式加载第三方模块

多线程打包

抽离公共文件

6.缓存和压缩

客户端缓存、服务端缓存

服务端Gzip压缩

Vue中的修饰符有哪些?

  1. 事件修饰符
  • stop 阻止冒泡

  • prevent 阻止默认行为

  • capture 内部元素触发的事件先在次处理

  • self 只有在event.target是当前元素时触发

  • once 事件只会触发一次

  • passive 立即触发默认行为

  • native 把当前元素作为原生标签看待

  1. 按键修饰符
  • keyup键盘抬起

  • keydown 键盘按下

  1. 系统修饰符
  • ctrl

  • alt

  • meta

  1. 鼠标修饰符
  • left 鼠标右键

  • middle 鼠标中键

  • right 鼠标右键

  1. 表单修饰符
  • lazy 等输入完之后再显示

  • stop 删除内容前后的空格

  • type 输入是数字或专为数字

7. V-Router 几种模式的区别

V-Router 有三种模式hash,history,abstract

abstract模式是在不支持浏览器API环境使用,不依赖于浏览器历史

hash模式:hash+popState/hashChange 兼容性好但是不够美观,hash服务端无法获取。不利于seo优化

history模式:historyApi + popState 美观,刷新会出现 404 -> CLI web pack history-fallback

如何解决刷新后二次加载路由

1.window.location.reload()

2.matcher

const router = createRouter()

export function resetRouter(){

const newRouter = createRouter()

router.matcher = newRouter.matcher

}

Vue中如何做强制刷新

1.localtion.reload()

2.this.$router.go(0)

3.provide 和 inject

大文件上传是怎么做的

分片上传:
  1. 把需要上传的文件按照一定的规则,分隔成相同大小的数据块

  2. 初始化一个分片上传任务,返回本次分片上传的唯一标识

  3. 按照一定的规则把各个数据块上传

  4. 发送完成后,服务端会判断数据上传的完整性,如果完整,那么就会把数据库合并成原始文件

断点续传:

服务端返回,从哪里开始,浏览器自己也可以处理

什么是语义化标签

1.易读性和维护性更好

2.seo成分会更好,蜘蛛抓取会更好

3.IE8不兼容HTML5标签的。解决:可以通过html5shiv.js去处理。

例如:

<header></header>、<footer></footer>、<section></section>、<button></button>

title与h1的区别,b与strong的区别,i与em的区别

title与h1的区别:

定义:

title:概括了网站信息,可以告诉搜索引擎或者用户关于这个网站的内容主题是什么

h1:文章主题内容,告诉蜘蛛我们的网站内容最主要是什么

区别:

title他是显示在网页标题上、h1是显示在网页内容上

title比h1添加的重要(title > h1) => 对于seo的了解

场景:

网站的logo都是用h1标签包裹的

b与strong的区别

定义:

b:实体标签,用来给文字加粗的。

strong:逻辑标签,用来加强字符语气的

区别:

b标签只有加粗的样式,没有实际含义。

strong表示标签内字符比较重要,用以强调的

题外话:为了CSS3的规范,b尽量少用该用

i与em的区别

定义:

    i:字体标签,用来文字倾斜的

    em:是逻辑标签,用来强调文字内容的

区别:

    i只是一个倾斜标签,没有实际含义。

    em表示标签内字符重要,用以强调的

场景:

    i更多的用在字体图标,em术语上(医药,生物)。

img标签的title和alt有什么区别?

区别一:

title:鼠标移入到图片显示的值

alt:图片无法加载时显示的值

区别二:

在seo的层面上,蜘蛛抓取不到图片的内容,所以前端在写img标签的时候为了增加seo效果要加入alt属性来描述这张图是什么内容或者关键词。

png,jpg,gif这些图片格式解释一下,分别什么时候用?

png:无损压缩,尺寸体积要比jpg/jpeg的大。适合做小图标,不适合做banner,加载慢。

jpg;采用压缩算法,有一点失真,比png体积要小。(做中大型图片)

gif:一般是做动图的。

webp:同时支持有损或者无损压缩,相同质量的图片,webp具有更小的体积。兼容性不是特别好。

如何关闭iOS键盘首字母自动大写

<input type autocapitalize = "off">

怎么让Chrome支持小于12px的文字?

Chrome默认font-size:16px,每个浏览器默认字体大小可能都不一样

<div>
    <span>你好呀~</span>
</div>

div {
    font-size:10px;
}
div span {
    display:inline-block;
    -webkit-transform:scale(1.6)
}

iOS系统中元素被触摸时产生的半透明灰色遮罩怎么去掉

<style>
    a,button,input,textarea{
    
        -webkit-tap-highlight-color:rgba(0,0,0,0)
    }
</style>

webkit表单中输入框placeholder的颜色值能改变吗?

<style>
    input::-webkit-input-placeholder{
       color:red
    }
</style>

禁止iOS长按时触发系统的表单,禁止iOS&android长按时下载图片

禁止iOS长按时触发系统的菜单,禁止iOS&android长按时下载图片

html,body{
    touch-callout:none;
    -webkit-touch-callout:none;
    user-select:none;
    -webkit-user-select:none;

}

禁止iOS和android用户选中文字

html,body{
    user-select:none;
    -webkit-user-select:none;
}

用CSS画一个三角形

用边框画(border)

{
    width:0;
    height:0
    border-left:100px solid transparent;
    border-right:100px solid transparent;
    border-top:100px solid transparent;
    border-bottom:100px solid #ccc;
}

在网页中的应该使用奇数还是偶数的字体?为什么呢? 

偶数:让文字在浏览器上表现更好看

另外说明:Ui给前端一般设计图都是偶数的,这样不管是布局也好,转换ps也好,方便一点

什么是CSS reset

reset 是一个css文件,用来重置css样式的

Normalize.css 为了增强跨浏览器渲染的一致性,一个css重置样式库。

css sprite 是什么。有什么优缺点

1.把多个小图标合并成一张大图片,

2.优缺点:减少了http请求的次数,提升了性能,维护比较差(例如图片位置进行修改或者内容宽高修改)

页面导入样式时,使用link 和 @import 的区别?

区别一:link先有,后有@import(兼容性比@import好)

区别二:加载顺序差别:浏览器先加载的标签link,后加载@import