JS 基础知识巩固(JS面试宝典-全面透彻)

1.  值类型

var a = 100
var b = a
a = 200
console.log(b)  // 100

2.引用类型 

var a = {age:100}
var b = a 
a.age = 200
console.log(a.age) // 200

问题:为什么对值类型和引用类型进行修改会出现不同的结果呢?
答:值类型:存的是具体的数值,比如 a=200,那么 a 变量内存中地址存的就是 200。所以改变 a=100 ,仅仅只是影响到了 a。
引用类型:内存中存的是对象的地址,所以 a 和 b 此刻指向了同一个对象的地址。改变 a.age 就会同时影响到 b.age。

3.引用类型包括

对象、数组、函数(为什么需要用到引用呢?因为这些类型可能非常大,每次赋值都新建一个新对象,就会比较浪费空间)

4.typeof 运算符

typeof undefined        // undefined
typeof 'abc'            // string
typeof 123              // number
typeof true             // boolean
typeof {}               // object
typeof []               // object
typeof null             // object (它也是引用类型)
typeof console.log      // function

结论: typeof 能区分值类型;对于引用类型只能区分 function 其他无法区分。

5.问:JS 中有哪些内置函数 -- 数据封装类对象

   答:

Object
Array
Boolean 
Number
String
Function
Date
RegExp
Error

第二章:JS 基础上篇(原型和原型链) 

 

  • var a = {} 其实是 var a = new Object() 的语法糖
  • var a = [] 其实是 var a = new Array() 的语法糖
  • function Foo(){...} 其实是 var Foo = new Function(){...}
  • 使用 instanceof 判断一个函数是否是一个变量的构造函数.


总结:引用类型都有一个构造函数

  •  下写一个原型链继承的例子
function Animal() {
    this.eat = function () {
        console.log('animal eat')
    }
}

function Dog() {
    this.bark = function () {
        console.log('dog bark')
    }
}

Dog.prototype = new Animal();

let hashiqi = new Dog()

hashiqi.bark()
hashiqi.eat()

描述 new 一个对象的过程 

  • 建一个新对象
  • this 指向这个新对象
  • 执行代码,即对 this 赋值
  • 返回 this

第三章:JS 基础中篇(作用域和闭包)

1.表达式和声明的区别

fn()                        // 输出: fn
// fn1()                    // 输出: fn1 is not a function
console.log(a);             // 输出: undefined

// 这个叫做"声明"
function fn() {
    console.log('fn');
}

// 这个叫做"表达式"
var fn1 = function () {
    console.log('fn1');
}

// 这个叫做"表达式"
var a = 100;
  • JavaScript 解释器中存在一种变量声明被提升的机制,也就是说函数声明会被提升到作用域的最前面,即使写代码的时候是写在最后面,也还是会被提升至最前面。
  • 而函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用。

前面的函数,相当于如下写法:

// 这个叫做"函数声明"
function fn() {
    console.log('fn');
}
var a = undefined;
var fn1 = undefined;

fn()                        // 输出: fn
// fn1()        // error: fn1 is not a function
console.log(fn1);   // 输出: undefined
console.log(a); // 输出: undefined


// 这个叫做"表达式"
var fn1 = function () {
    console.log('fn1');
}

// 这个叫做"表达式"
var a = 100;

2. 函数内部会默认有 this 和 arguments 自带变量

fn('zhansan')
function fn(name) {
    console.log(this);                //输出:复杂对象
    console.log(arguments);   //输出:{ '0': 'zhansan' }

    age = 20
    console.log(name, age);   //输出:zhansan 20
    var age 
}

3.this 要在执行时才能确认值,定义时无法确认 

let a = {
    name: 'A',
    fn: function () {
        console.log(this.name)
        // console.log(this)
    }
}

a.fn()                // this === a
a.fn.call({ name: 'B' })  // this === {name:'B'}
this.name = 'here'  
this.fn1 = a.fn
this.fn1()         // this === window

4.JavaScript 无块级作用域 

if (true) {
    var name = 'zhansan'
}
console.log(name);   // 输出:  name === 'zhansan'

5.JavaScript 有 函数作用域和全局作用域 

var a = 'global'
function fn() {
    var a = 'function'
    console.log(a);
}
fn()    // 输出 'fn'
console.log(a);    // 输出 'global'

6.作用域链:就是函数定义的时候,内部使用的变量没有进行定义,会向父级作用域寻找该变量。

函数作用域中使用没有在本函数作用域中的变量叫做自由变量:自由变量的定义一定是在定义时候的父级作用域去寻找。

var a = 100
function F1(){
    var b = 200
    function F2(){
        var c = 300
        console.log(a);
        console.log(b);
        console.log(c);
    }
    F2()
}
F1()

7.闭包-闭包的定义,自己从下面 代码一作为返回值、代码二作为参数 中体会。 

// 代码一:闭包作为返回值
function F1() {
    var a = 100
    // 返回一个函数(函数作为返回值)
    return function(){
        console.log(a);  // 自由变量,父级作用域寻找 
    }
}
// f1 得到一个函数
var f1 = F1()
var a = 200
f1() // 输出: 100
// 代码二:闭包作为参数值
function F1() {
    var a = 100
    // 返回一个函数(函数作为返回值)
    return function(){
        console.log(a); // 自由变量,父级作用域寻找
    }
}
// f1 得到一个函数
var f1 = F1()
function F2(fn) { 
    var a = 200
    fn()
}
F2(f1)  // 依然输出:    100

8.闭包实际应用中主要用于封装变量,收敛权限。

function isFirstLoad() {
    var _list = []
    return function (id) {
        if (_list.indexOf(id) >= 0) {
            return false
        } else {
            _list.push(id)
            return true
        }
    }
}

// 使用
var firstLoad = isFirstLoad()
console.log(firstLoad(10));     // true
console.log(firstLoad(10));     // false
console.log(firstLoad(20));     // true

上面的代码,使用闭包,就会将 _list 很好的隐藏起来,保护它的其他操作权限。 

 

第四章:JS 基础下篇(异步和单线程、其他知识点)

1.什么是异步?什么是同步?setTimeout() 就是异步(不阻塞代码),alert()就是同步(阻塞代码)。

2.什么是单线程?就是一次只能做一件事情,类似一次执行一行代码。

3.日期

Date.now() // 获取当前时间毫秒数
var dt = new Date()
dt.getTime()  // 获取毫秒数
dt.getFullYear()  // 年
dt.getMonth()  // 月(0-1)注意:这里是比较特殊
dt.getDate()  // 日 (1-31)
dt.gatHours() // 小时(0-23)
dt.getMinutes() // 分钟 (0-59)
dt.getSeconds()  // 秒 (0-59)

4.math 主要应用:math.random() 获取一个 0-1 之间的随机数 

第五章:JS-Web-API 上篇(DOM 、 BOM)

  • 常说的 JS(浏览器执行的 JS)包含两部分:

① JS 基础知识( ECMA262 标准 )
② JS-Web-API( W3C 标准 )

  • DOM 的本质是什么? 

浏览器把拿到的 HTML 代码,结构化成一个浏览器能识别并且 JS 可操作的一个模型而已。

  • 获取 DOM 节点(最常用的几种) 
var div1 = document.getElementById('div1')  //元素
var divList = document.getElementsByTagName('div')  //集合
var containerList = document.getElementsByClassName('container')    //集合
console.log(divList.length)
console.log(divList[0])
console.log(containerList.length)

var pList = document.querySelectorAll('p')  //集合
var p = pList[0]
console.log(p.style.width)
p.style.width = '200px' // 改变宽度
console.log(p.style.width)
console.log(p.className)
p.className = 'p2class'
// 获取 nodeName 和 nodeType
console.log(p.nodeName)
console.log(p.nodeType)
  • Property 和 Attribute 中文翻译都是‘属性’,有什么不同呢? 
var pList = document.querySelectorAll('p')  //集合
var p = pList[0]
p.style.width   // 这里就是 property  改的是 JS 对象的属性
p.setAttribute('data-name', 'helloworld')  //  改的是 dom 文档的属性
p.setAttribute('style', 'font-size: 26px;')
console.log(p.getAttribute('data-name'))
console.log(p.getAttribute('style'))
  • navigator & screen (BOM 内置变量) 
// navigator 判断浏览器
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(!!isChrome)

// screen 判断窗体大小
console.log(screen.width)
console.log(screen.height)
  • location & history 
// location
console.log(location.href) // 'https://www.baidu.com/s?wd=aaa'
console.log(location.protocol) // 'https:'
console.log(location.host) // www.baidu.com
console.log(location.pathname) // '/s'
console.log(location.search) // ?号后面的内容  wd=aaa

// history
history.back()
history.forward()

第六章:JS-Web-API 下篇(事件、跨域、存储) 

  • 通用事件绑定(写一个通用事件绑定方法,可以减少方法名长度) 

event.preventDefault() // 阻止控件的默认事件 

var btn = document.getElementById('btn1')
btn.addEventListener('click',(event)=>{
    console.log('click')
})

function bindEvent(element, type, fn) {
    element.addEventListener(type, fn)
}
var a = document.getElementById('link1')
bindEvent(a, 'click', (event)=> {
    event.preventDefault() // 阻止 a 标签默认行为
    alert('clicked')
})
  • 事件冒泡 

event.stopPropagation() // 阻止事件冒泡 

 问:如何让所有<p>绑定点击事件,使得点击激活;执行激活操作,点击取消,执行取消操作。

<body>
    <div id="div1">
        <p id="p1">激活</p>
        <p id="p2">取消</p>
        <p id="p3">取消</p>
        <p id="p4">取消</p>
    </div>
    <div id="div1">
        <p id="p5">取消</p>
        <p id="p6">取消</p>
        <p id="p7">取消</p>
        <p id="p8">取消</p>
    </div>
</body>

答:根据事件冒泡原理,我们可以先绑定 body 的事件。

<script>
    var body = document.body
    body.addEventListener('click',(event)=>{
        alert('取消')
    })
    var activeDiv = document.getElementById('p1')
    activeDiv.addEventListener('click',(event)=>{
        event.stopPropagation();    //阻止事件继续向上冒泡
        alert('激活');
    })
</script>

问题如下:如何让程序实现点击 a 标签,弹出 a 标签内的内容?

<div id="div1">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <a href="#">a3</a>
    <a href="#">a4</a>
    <!-- 会随时新增更多 a 标签 -->
</div>

答:通过 event.target 可以获取点击事件触发的最顶层控件 

<script>
    let div1 = document.getElementById('div1')
    div1.addEventListener('click',(event)=>{
        let target = event.target
        if (target.nodeName === 'A') {
            alert(target.innerHTML)
        }
    })
</script>
  • 什么是跨域? 
  • 浏览器有同源策略,不允许 ajax 访问其他域接口。
  • 跨域条件:协议、域名、端口,有一个不同就算跨域。
  • 有哪三个标签运行跨域访问? 
  • <img src=xxx>
  • <link src=xxx>
  • <script src=xxx>
  • 三个标签的特殊应用场景? 
  • <img> 用于打点统计,统计网站可能是其他域
  • <link><script> 可以使用 CDN,CDN 也是其他域
  • <script> 可以用 JSONP。👇下面代码展示什么是 JSONP
  • 本地存储之 cookie 
  • 本身用于客户端和服务器端通信
  • 但是它有本地存储的功能,于是就被“借用”
  • 使用 document.cookie = ... 获取和修改即可
  •  cookie 用于存储的缺点
  • 存储量太小,只有 4KB
  • 所有 http 请求都带着,会影响获取资源的效率
  • API 简单,需要封装才能用 document.cookie = ...
  •  locationStorage 和 sessionStorage
  • HTML5 专门为存储而设计,最大容量 5M
  • API 简单易用
  • localStorage.setItem(key, value); localStorage.getItem(key);
  •  locationStorage 和 sessionStorage
  • iOS safari 隐藏模式下
  • localStorage.getItem 会报错
  • 建议统一使用 try-catch 封装

第七章:模块化 

  • 先看不用模块化的代码会出现的问题。有如下说明代码:
// util.js
function getFormatDate(date, type){
  // type === 1 返回 2019-04-30
  // type === 2 返回 2019 年4 月 15 日
  // ...
}

// a-util.js
function aGetFormatDate(date) {
  // 要求返回 返回 2019 年4 月 15 日 格式
  return getFormatDate(date, 2)
}

// a.js
let dt = new Date()
console.log(aGetFormatDate(dt))

对于上述代码的调用:

<script src="util.js"></script>
<script src="a-util.js"></script>
<script src="a.js"></script>
  1. 这些代码中的函数必须是全局变量,才能暴露给使用方。容易造成全局变量污染。
  2. a.js 知道药引用 a-util.js ,但是他知道还需要依赖于 util.js 吗?
  •  使用模块化。有如下说明代码:
// util.js
export {
  getFormatDate: function (date, type){
    // type === 1 返回 2019-04-30
    // type === 2 返回 2019 年4 月 15 日
    // ...
  }
}

// a-util.js
var getFormatDate = require('util.js')
export {
  aGetFormatDate: function (date){
    return getFormatDate(date, 2)
  }
}

// a.js
var aGetFormatDate = require('a-util.js')
let dt = new Date()
console.log(aGetFormatDate(dt))

 模块化的代码有如下好处:

  • 直接<script src="a.js"></script>,其他的根据依赖关系自动引用。
  • 那两个函数,没必要做成全局变量,不会来带污染和覆盖。

 第八章:运行环境

  • 浏览器加载一个资源的过程
  1. 浏览器根据 DNS 服务器得到域名的 IP 地址
  2. 向这个 IP 的机器发送 http 请求
  3. 服务器收到、处理并返回 http 请求
  4. 浏览器得到返回内容
  •  浏览器渲染页面的过程
  1. 根据 HTML 结构生成 DOM Tree
  2. 根据 CSS 生成 CSSOM
  3. 将 DOM 和 CSSOM 整合形成 RenderTree
  4. 根据 RenderTree 开始渲染和展示
  5. 遇到 <script> 时,会执行并阻塞渲染

  • window.onload 和 DOMContentLoaded
window.addEventListener('load', function(){
  // 页面全部资源加载完成才会执行,包括图片、视频等
})
document.addEventListener('DOMContentLoaded', function() {
  // DOM 渲染完成即可执行,此时图片、视频还可能没有加载完
})
  • 性能优化

原则

  • 多使用内存、缓存
  • 减少 CPU 计算、减少网络请求 、 减少 DOM 操作
  • 加载资源优化
  1. 静态资源的压缩合并
  2. 静态资源缓存
  3. 使用 CDN 让资源加载更快
  4. 使用 SSR 后端渲染,数据直接输出到 HTML 中
  • 渲染优化
  1. CSS 放前面,JS 放后面
  2. 懒加载(图片懒加载、下拉加载更多)
  3. 减少 DOM 查询,对 DOM 查询做缓存
  4. 减少 DOM 操作,多个操作尽量合并在一起执行
  • 事件节流
  1. 尽早执行操作(如 DOMContentLoaded)
  2. 安全性之 XSS (全称跨站脚本攻击)
  3. 在新浪博客写一篇文章,同时偷偷插入一段<script>
  4. 攻击代码中,获取 cookie ,发送到自己的服务器
  5. 发布博客,有人查看博客内容,会执行代码。
  6. 解决方案:前端或者后端替换关键字,例如替换 < 为 &lt ; > 为 &gt ;
  • 安全性之 XSRF (全称跨站请求伪造)
  1. 你已登录一个购物网站,正在浏览商品
  2. 该网站的付费接口是 xxx.com/pay?id=100 但是没有任何验证
  3. 然后你收到一封邮件,隐藏着<img src=xxx.com/pay?id=100>
  4. 当你查看邮件的时候,就已经悄悄的付费购买了
  5. 解决方案:增加验证流程,如输入指纹、密码、短信验证码。或者服务端更多信息的校验。


 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值