JavaScript高级教程(javascript实战进阶)

news/2025/1/12 6:00:39/

javascript高级、面试常问、必备知识点

  • 1.数据类型
  • 2.引用变量赋值问题
  • 3. 对象和函数
  • 4.函数原型与原型链
    • 面试题一
    • 面试题二
    • 面试题一分析
    • 面试题二分析
    • 原型链注意点
  • 5.执行上下文和执行上下文栈
    • 面试题一
    • 面试题二
    • 面试题一分析
    • 面试题二分析
  • 6.作用域
    • 面试题一
    • 面试题二
    • 面试题一分析
    • 面试题二分析
  • 7.闭包
  • 8.线程与事件循环


1.数据类型

分类:

  • 基本数据(值)类型
    • String:任意字符串
    • Number:任意的数字
    • boolean:true/false
    • undefined:undefined
    • null:null
  • 对象(引用)类型
  • Object:任意对象
  • Function:一种特别的对象(可以执行)
  • Array:一种特别的对象(数值下标,内部数据是有序的)

判断:

  • typeof:可以判断undefined、数组、字符串、布尔值、函数
    • 不能判断null和object
  • instanceof:可以判断对象的具体类型
  • ===:可以判断undefined、null( 因为都只有一个值)

undefined衍生至null

console.log(undefined == null) // true

2.引用变量赋值问题

(很重要!)
变量赋值是将一个变量的内容(基本数据类型的值或引用数据类型的地址值)拷贝一份给另一个变量

n个引用变量指向同一个对象,通过一个变量修改对象内部数据,其它所有变量看到的是修改后的数据
2个引用变量指向同一个对象,让其中一个引用变量指向另一个对象,另一引用变量依然指向前一对象

3. 对象和函数

对象:
对象中所有属性名都为字符串,但可以省略属性名的单引号或双引号,例如:name:'张三'
访问对象内部数据:.属性名   [‘属性名’]
只能使用 [‘属性名’]情况:

  1. 当属性名包含特殊字符: -   空格,例如:p[‘content-type’]
  2. 变量名不确定:var propName = 'myAge' var value = 18 p[propName] = value

函数中this问题:
任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
所有函数内部都有一个this
它的值是调用函数的当前对象
具体可以看着篇文章

4.函数原型与原型链

函数的prototype属性

  • 每个函数都有一个prototype属性,可称为显示原型(属性),它默认指向一个Object空对象(即称为:原型对象)
  • 原型对象中有一个属性constructor,它指向函数对象
  • 给原型对象添加属性(一般都是方法),作用:让函数的所有实例对象自动拥有原型中的属性(方法)

实例对象的__proto__属性

  • 每个实例对象都有一个__proto__,可称为隐式原型(属性)
  • 对象的隐式原型的值为其对应构造函数的显示原型的值
  • 例:Fn.prototype === fn.__proto__

原型链
访问一个对象的属性时

  • 先在自身属性中查找,找到返回;
  • 如果没有,再沿着__proto__这条链上查找,找到返回;
  • 如果都没有找到,则返回undefined

别名:隐式原型链
作用:查找对象的属性(方法)

在这里插入图片描述

注意点:

  • 所有函数对象的__proto__都是一样的,都指向Function的prototype(都是new Function出来的)
  • 函数的显示原型指向的对象默认是空的Object实例对象,但Object不满足,例:Object.prototype instanceof Object // false(因为A instanceof B,是判断B的显示原型是否在A的原型链上,而Object.prototype指向上图中Object的原型对象,其已经是原型链的尽头了)
  • 所有函数都是Function的实例(包含Function)
  • Object的原型对象是原型链的尽头

面试题一

function A(){}
A.prototype.n = 1
var b = new A()
A.prototype = {n:2,m:3
}
var c = new A()
console.log(b.n,b.m,c.n,c.m)

面试题二

function F (){}
Object.prototype.a = function(){console.log('66')
}
Function.prototype.b = function(){console.log('88')
}
var f = new F()
f.a()
f.b()
F.a()
F.b()

在这里插入图片描述

面试题一分析

输出:1 undefined 2 3
分析:b.n可通过b的隐式原型链查找,而b.m查不到,由于把一个新对象赋值给了A函数的显示原型,因此c的隐式原型指向会发生更改,指向A函数新的显示原型
在这里插入图片描述

面试题二分析

输出:66 报错 66 88
分析:查找f.a时,本身没有,沿着其隐式原型链可查到Object函数的原型对象上,查找成功,执行a函数,但无法查询到f.b,因为此时已是原型链的尽头了,因返回undefined,此执行f.b()报错。同理F.a和F.b都可以通过隐式原型链查询到。
(以下原型对象没有区分名字,且忽略了地址)在这里插入图片描述

原型链注意点

  • 通过图中标记一、二、三,可以得知每个函数都有显示原型和隐式原型(都是new Function()出来的,其都指向Function的显示原型)
  • 标记一可知,Function是特例,其显示原型和隐式原型(也是new Function()出来的)指向相同
  • 标记二可知,Object函数对象也是new Function()出来的,其隐式原型指向Function的显示原型
  • 标记三可知,任何函数其隐式原型都指向Function的显示原型

5.执行上下文和执行上下文栈

变量声明提升

  • 通过var定义(声明)的变量,在定义语句之前就可以访问到
  • 值:undefined

变量提升先于函数提升

函数声明提升

  • 通过function声明的函数,在之前就可以直接调用

全局执行上下文
在执行全局代码前将window确定为全局执行上下文
对全局数据进行预处理

  • var 定义的全局变量,undefined,添加为window的属性
  • function声明的全局函数,添加为window的方法
  • this赋值为window

开始执行全局代码

函数执行上下文
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
对局部数据进行预处理
-形参变量赋值为实参,添加为执行上下文的属性

  • arguments赋值实参列表,添加为执行上下文的属性
  • var定义的局部变量,undefined,添加为执行上下文的属性
  • function声明的函数,添加为执行上下文的方法
  • this赋值为调用函数的对象

开始执行函数体代码

面试题一

var a = 3
function fn(){console.log(a)var a = 4
}
fn()

面试题二

var c =1
function c(c){console.log(c)var c = 3
}
c(2)

面试题一分析

输出:undefined
分析:在函数体内,使用var定义的变量,声明为局部变量,又由于存在变量提升,因此源代码相当于以下代码

var a = 3
function fn(){var aconsole.log(a)a = 4
}
fn()

面试题二分析

输出:报错
分析:var定义的变量和函数声明式创建的函数会提升,因此源代码相当于以下代码,c为变量,无法执行c(2)

var c
function c(c){console.log(c)var c = 3
}
c = 1
c(2)

6.作用域

面试题一

var x = 10
function fn(){console.log(x)
}
function show(f){var x = 20fn()
}
show(fn)

面试题二

 var fn = function(){console.log(fn)}fn()var obj = {fn2:function(){console.log(fn2)}}obj.fn2()

面试题一分析

输出:10
分析:作用域在代码编写完毕时就已经确定了。执行fn(),找到的x为全局作用域x。

面试题二分析

输出:fn函数  报错
分析:第一个输出很好理解。第二个,当执行obj.fn2(),首先在函数内部作用域找fn2,找不到,则去外部全局作用域中找fn2,找不到。若想找到,应该使用this.fn2。这里要区分以下三种输出。

 var obj = {fn2:function(){console.log(fn2)console.log(this.fn2)console.log(window.fn2)}}obj.fn2()

7.闭包

//利用闭包实现循环遍历加监听
for(var i = 0,length=btns.length;i<length;i++){(function(i){var btn = btns[i]btn.onclick = function(){alert('第'+(i+1)+'个')}})(i)
}

如何产生闭包?

  • 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(或函数)时,就产生了闭包

闭包是什么? 通过chrome浏览器,在debug下查看

  • 理解一:闭包是嵌套的内部函数(绝大部分人)
  • 理解二:闭包是包含被引用变量(或函数)的对象(极少数人)
    注意:闭包存在于嵌套的内部函数中

产生闭包的条件?

  • 函数嵌套
  • 内部函数引用了外部函数的数据(变量/函数)
  • 执行外部函数,也即要执行内部函数定义就会产生闭包(不用执行内部函数)

常见的闭包?

  • 将函数作为另一个函数的返回值
  • 将函数作为实参传递给另一个函数调用

闭包的作用?

  • 使用函数内部的变量在函数执行后,仍然存活在内存中(延长了局部变量的生命周期)
  • 让函数外部可以操作(读写)到函数内部的数据(变量/函数)

闭包的产生和死亡?

  • 产生:在嵌套内部函数定义执行完时就产生了(不是调用,有函数提升)
  • 死亡:在嵌套的内部函数成为垃圾对象时
    注意:产生闭包的个数,看外部函数执行的次数

闭包的缺点?

  • 函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
  • 容易造成内存泄露
    解决:能不用闭包就不用,及时释放

闭包应用:自定义JS模块

具有特定功能的js文件
将所有的数据和功能都封装在一个函数内部(私有的)
只向外暴露一个包含n个方法的对象或函数
模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能

内存溢出与内存泄露

内存溢出

  • 一种程序运行出现的错误
    当程序运行需要的内存超过了剩余的内存时,就会抛出内存溢出的错误

内存泄露

  • 占用的内存没有及时释放
  • 内存泄露积累多了就容易导致内存溢出
  • 常见的内存泄露:意外的全局变量、没有及时清理的计时器或回调函数、闭包

8.线程与事件循环

进程与线程

  • 应用程序必须运行在某个进程的某个线程上
  • 一个进程中至少有一个运行的线程:主线程,进程启动后自动创建
  • 一个进程中也可以同时运行多个线程,可说程序是多线程运行的
  • 一个进程内的数据可以供其中的多个线程直接共享
  • 多个进程之间的数据是不能直接共享的
  • 线程池是用来保存多个线程对象的容器,实现线程对象的反复利用

JS单线程,浏览器多线程

具体事件循环面试题可以看篇文章

在这里插入图片描述

若有错误,请即时留言,不胜感激!


http://www.ppmy.cn/news/120958.html

相关文章

Android 10.0WallpaperPicker2添加动态壁纸服务

1.概述 在10.0的系统产品开发中,在定制化开发中,由于需要动态壁纸,而系统自带的只有默认的静态壁纸, 所以需要添加动态壁纸的功能 2.WallpaperPicker2添加动态壁纸服务的核心类 packages\apps\WallpaperPicker2\src\com\android\wallpaper\widget\GIFWallpaperService.j…

关键字 package、import的使用

一、package 关键字的使用 为了更好的实现项目中类型的管理&#xff0c;提供了包的概念使用package声明类或接口所属的包&#xff0c;声明在源文件的首行包 术语标识符&#xff0c;遵循标识符的命名规则、规范&#xff08;xxxyyyzzz&#xff09;、“见名知意”每 “ . ”一次&…

GB28181——实时视频显示

一、主要实现功能 1、支持四路设备接入 2、实时视频分屏显示 3、接入设备信息存储 二、待完善功能&#xff08;现阶段&#xff09; 1、设备的删除 &#xff08;已更新&#xff09; 2、语音对讲 &#xff08;暂时不处理&#xff09; 3、视频输出通道的实时修改 &#xff08;已更…

clickhouse简介

文章目录 1&#xff1a;简介1.1&#xff1a;CH是什么&#xff1f;1.2&#xff1a;CH优势1.3&#xff1a;架构设计 2&#xff1a;CH接口3&#xff1a;CH引擎1&#xff1a;数据库引擎3.1.1:mysql引擎 2&#xff1a;表引擎3.2.1&#xff1a;MergeTree3.2.2&#xff1a;集成引擎1&a…

软件开发:面向对象设计的七大原则!

七大原则 开闭原则、里氏代换原则、迪米特原则&#xff08;最少知道原则&#xff09;、单一职责原则、接口分隔原则、依赖倒置原则、组合/聚合复用原则。 开闭原则&#xff08;The Open-Closed Principle &#xff0c;OCP&#xff09; 开闭原则&#xff1a;软件实体&#xff…

关于宏基暗影骑士擎笔记本如何关闭触摸板的问题记录

1.选择左下角设置按钮&#xff0c;点击 2.选择触摸板&#xff0c;在右边关闭即可

宏基笔记本怎么进入BIOS界面

方法一 1.开机不断按F12 方法二 1.插入U盘启动盘&#xff0c;开机时不停按F2进bios&#xff0c;按→方向键移动到Boot&#xff0c;选择Secure Boot回车&#xff0c;改成Disabled&#xff1b; 2.在Main下&#xff0c;将F12 Boot Menu设置成Enabled&#xff0c;最后按F10回车保存…

Acer宏基笔记本电脑宏碁暗影骑士擎AN515-58原装出厂恢复原厂预装Windows11/10镜像oem系统

Acer宏基笔记本电脑宏碁暗影骑士擎AN515-58原装出厂恢复原厂预装Windows10/11镜像oem系统(以及AN515-43、AN515-46、AN515-52、AN515-54、AN515-55、AN515-57、AN515-58等) 文件分享地址链接&#xff1a;https://pan.baidu.com/s/1pLwVIz02OLfTAzWDfN-HMg?pwdx515 1.完全恢…