javascript高级基础的深入总结

本文深入讲解JavaScript的基础知识,包括数据类型、内存管理、变量、对象、函数等内容,并探讨了闭包、原型链、继承模式等高级主题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础总结深入

1、数据类型

分类

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

判断

  • typeof
  • instanceof
  • ===(全等,不会做数据转换) | ==(会做数据转换)

1、undefined和null的区别?

undefined 代表定义未赋值

null 代表定义并赋值了,只是值为null

2、什么时候给变量赋值为null?

起始的时候初始赋值为null,表明将要赋值为对象。

var b = null;

确定对象就赋值

b = [] || b = {}

最后,释放资源,让变量指向的对象成为垃圾对象(被回收)

b = null

3、严格区别变量类型与数据类型

变量类型

  • 基本类型
  • 对象类型

数据类型

  • 基本类型:保存的就是基本类型的数据
  • 引用类型:保存的是地址值

2、数据,变量与内存

1、什么是数据?

存储在内存中代表特定信息的“东东”,本质上是010101…

数据的特点:可传递(基本类型传递的是指,引用类型传递的是地址值)、可运算

2、什么是内存?

内存只是一种概念,现实形象的就是内存条了,内存条通电后产生的课存储数据的空间(临时的)

内存产生和死亡:内存条(电路板)–> 通电–> 产生内存空间–> 存储数据–> 处理数据–> 断电–> 内存空间和数据读消失

一块小内存的2个数据:地址值与存储的数据。

内存分类:

  • 栈:全局变量、局部变量
  • 堆:对象(对象本身在堆空间中,但是表示对象的标识(变量名)在栈空间中)

3、什么是变量?

可以变化的量,有变量名和变量值组成。常量是不嫩变化的量。

每个变量都对应一块小内存,变量名可用来查找对应的内存,变量值就是内存中保存的数据。

4、前三者之间的关系

内存用来存储数据的空间;

变量是内存的标识,

5、相关问题**

1、关于赋值与内存的问题?

问题:var a=xxx; a内存中到底保存的是什么?

  1. 如果xxx是基本数据,保存的就是这个数据
  2. 如果xxx是对象,保存的是对象的地址值
  3. 如果xxx是变量,保存的是xxx的内存内容(可能是基本数据,也可能是地址值)

2、关于引用变量赋值问题?

小总结一下:关于变量赋值问题:

  • 如果变量所指向的是基本类型,则赋值是直接将保存的值复制过去。
  • 如果变量所指向的是引用类型,则赋值是将保存的地址值复制过去。

多个引用变量指向同一个对象,通过一个变量修改对象内部的数据,其他变量看到的是修改之后的数据。

var obj1 = {name:"wwj"}
var obj2 = obj1;
obj2.name = "Tom";
console.log(obj1.name + "---" + obj2.name);		//Tom---Tom

// ======
function fun(obj){
    obj.name = "A";
}
fun(obj2);	// 把实参obj2的值赋值给形参,即把obj2变量保存的对象的地址值赋值给形参。
console.log(obj1.name + "---" + obj2.name);	//A---A

2个引用变量指向同一个对象,让其中一个引用变量指向另一个对象,另一个引用变量依然指向前一个对象。

var a = {age:31}
var b = a;
a={name:"wwj", age:18};
console.log(b.age + "---" + a.name + "---" + a.age);//31---wwj---18

//==============
function fun2(obj){	
    // 说明:当调用fun2方法是,把实参变量a的值(即使对象的地址值)赋值给形参obj,obj为局部变量,这时,变量a和局部变量obj都是指向同一个对象。
    // 当局部变量obj重新指向另一个对象时,局部变量obj保存的地址值改变,而变量a的值没有改变,所以即使改变局部变量obj所指向的对象的值,也改变不了不了a所指向的对象的值。而当函数执行完毕后,清除局部变量obj
    obj = {age:88}
}
fun2(a);
console.log(a.name + "---" + a.age);	//wwj---18

3、在js调用函数时传递变量参数时,是值传递还是引用传递?

总结:

  • 都是值传递(基本类型的值|引用类型的地址值)
  • 如果变量所指向的是基本类型,则赋值是直接将保存的值复制过去。
  • 如果变量所指向的是引用类型,则赋值是将保存的地址值复制过去。
var a = 3;
function fun(a){
    a = a + 1;
}
fun(a)
console.log(a)	// 3

4、js引擎任何管理内存?

  • 内存生命周期
    • 分配小内存空间,得到它的使用权
    • 存储数据,可以反复进行操作
    • 释放小内存空间
  • 释放空间
    • 局部变量:函数执行完毕自动释放
    • 对象:成为垃圾对象==》垃圾回收期回收

3、对象

1、什么是对象?

  • 多个数据的封装体
  • 用来保存多个数据的容器
  • 一个对象代表现实中的一个事物

2、为什么要用对象?

  • 统一管理多个数据

3、对象的组成

属性:

  • 代表现实事物的状态数据
  • 由属性名和属性值组成
  • 属性名都是字符串类型,属性值是任意类型

方法:

  • 代表现实事物的行为数据
  • 是特别的属性==》属性值是函数

4、任何访问对象内部数据?

属性名:编码简单,但有时不能用

[“属性名”]:编码麻烦,但通用

4、函数

1、什么是函数?

实现特定功能的n条语句的封装体

只有函数是可以执行的,其他类型的数据不能执行

2、为什么要用函数?

提高代码复用

便于阅读交流

3、如何定义函数?

函数声明

  • function fun(){}
    

函数表达式

- ```js
var fun = function (){}

4、任何调用(执行)函数?

function fun(){
    test:function(){}
}

fun():直接调用

fun.test():通过对象调用

new fun():new调用

fun.call()|fun.apply():临时让某个对象调用

5、回调函数

1、什么函数才是回调函数?

  1. 自己定义的
  2. 而且自己没有调用
  3. 但是最终函数执行了
document.body.onclick = function(){
    alert("这个函数回调了")
}

2、常见的回调函数

  • 定时器回调函数
    • 超时定时器
    • 循环定时器
  • Dom事件回调函数
  • ajax请求回调函数
  • 生命周期回调函数

6、IIFE-立即执行函数

全称:Immediately-invoked Function Expression(立刻执行函数表达式 或立刻调用函数表达式)

作用:

  • 隐藏实现
  • 不会污染外部(全局)命名空间
  • 用来编码js模块
// 无惨
;(function(){
    alert("立即执行了")
})()

// 有惨
;!function(obj){
    alert("立即执行了---" + obj)
}("这是个参数...")

//===========
;-function(){
    alert("立即执行了")
}()

//===========
;+function(){
    alert("立即执行了")
}()

//===========
;~function(){
    alert("立即执行了")
}()

// ...... 

;!function() {
    var obj = {
        name: "wwj"
    }
    function fun() {
        console.log(obj);
    }
    window.$ = function() { // 向外暴露一个全局变量
        return {
            obj: obj,
            fun: fun
        }
    }
}()
// $ 是一个函数,函数返回一个对象。
$().fun();

7、函数中的this

查看js基础中的函数,有详细说明;

8、语句加不加分号

没有应该不应该,只有你自己喜欢不喜欢。

但是,有几种不加分号,在压缩代码的时候会有问题:

  1. 小括号开头的前一条语句
  2. 中方括号开头的前一条语句
  3. 定义变量的语句

函数高级

1、原型与原型链

1.1 原型-prototype

函数的prototype属性

  • 每个函数都有一个prototype属性,它默认指向一个Object空对象(空对象:没有我们的自定义的属性。并且这个Object空对象是Object对象的实例,所以有一个隐式属性__proto__)(即称为:原型对象)

    var obj = function() {
    }
    console.log(obj.prototype);
    obj = new obj();
    console.log(obj);
    console.log(Date.prototype);	
    
    • 当使用new 关键字创建一个实例是,都会有一个隐藏的属性__proto__,下面有讲解。。。
  • 原型对象中有一个属性Constructor,它指向函数对象

    var obj = function() {
    }
    console.log(obj.prototype.constructor === obj);
    console.log(Date.prototype.constructor === Date);
    

给原型对象添加属性(一般都是方法)

  • 作用:函数的所有实例对象自动拥有原型中的属性(方法)

在这里插入图片描述

var Fun = function() {
}
Fun.prototype.test = function(){
    alert("~~~");
}
var fun= new Fun();
fun.test();

1.2 显示原型月隐式原型

  1. 每个函数function都要一个prototype,即显式原型(属性)

    var Fun = function() {
    }
    console.log(Fun.prototype)
    Fun.prototype.test = function(){
        alert("~~~");
    }
    console.log(Fun.prototype)
    
  2. 每个实例对象都要一个__proto__,可称为隐式原型(属性)

    var Fun = function() {
    }
    Fun.prototype.test = function(){
        alert("~~~");
    }
    var fun= new Fun();
    console.log(Fun.__proto__)
    
  3. 对象的隐式原型的值为其对应构造函数的显示原型的值

    var Fun = function() {
    }
    Fun.prototype.test = function(){
        alert("~~~");
    }
    var fun= new Fun();
    fun.test();
    // 证明~~~
    console.log(fun.__proto__ === Fun.prototype)
    
  4. 内容结构(图)

  5. 在这里插入图片描述

  6. 总结:

    • 函数的prototype属性:在定义函数时自动添加的,默认值是一个空的Object对象
    • 对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性值
    • 程序员能直接操作显示原型,但不能直接操作隐式原型(ES6之前)

1.3 原型链

  1. 原型链(图解):(空对象:没有我们的自定义的属性。并且这个Object空对象是Object对象的实例,所以有一个隐式属性__proto__

在这里插入图片描述

在这里插入图片描述

  1. 访问一个对象的属性时,先在自身属性中查找,找到返回;如果没有,在沿着__proto__这条链向上查找,找到返回,如果最终都没找到,则返回undefined。

  2. 别名:隐式原型链

  3. 作用:查找对象的属性(方法)

  4. 构造函数 /原型/实体对象的关系(图解)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  5. 在这里插入图片描述

  6. 构造函数 /原型/实体对象的关系2(图解2)

    1. 任何的函数都是通过new Function() 创建的,无论是内置函数,还是自定义函数
    2. 实例对象的隐式原型等于构造函数的显式原型

在这里插入图片描述

在这里插入图片描述

补充:

  • 函数的显式原型指向的对象默认是空Object实例对象(但Object不满足):

    console.log(Fn.prototype instanceof Object)		// true
    console.log(Object.prototype instanceof Object)		// false
    console.log(Function.prototype instanceof Object)		// true
    
  • 实际上上图中的 Function.prototype 还有一个 __proto__属性,并且指向Object.prototype。

  • 所有函数都是Function的实例(包括Function)

    console.log(Function.prototype ===  Function.__proto__)		// true
    
  • Object的原型对象是原型链的尽头。并且__proto__的返回值为null

    console.log(Object.prototype.__proto__)		// null
    
1.3.1 属性问题
  • 读取对象的属性值时:会自动到原型链中查找(会先在对象本身上查找,没有则沿着原型链查找)
  • 设置对象的属性值时,不糊查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
  • 方法一般定义在原型中,属性一般通过构造函数定义在对象本身上。

1.4 探索instanceof

作用:判断左边的对象 是否是 右边类型的实例

表达式:A instanceof B

结果:如果B函数的显式原型对象在A对象的原型链上,返回true,否则返回false。

例子一:
在这里插入图片描述

例子二:

在这里插入图片描述

在这里插入图片描述

2、执行上下文与 执行上下为栈

1.变量提升与函数提升

  • 变量声明提升

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

    • 值:undefined

    • console.log(a);	// undefined
      var a = "xx";
      // 上面的代码相当于是:
      var a;
      console.log(a);	// undefined
      a = "xx";
      
  • 函数声明提升

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

    • 值:函数定义(对象)

    • b();
      function b(){
          console.log("~")
      }
      // 上面的代码相当于是:
      function b(){
          console.log("~")
      }
      b();
      
  • 问题:变量提升和函数提升是如何产生的?

    c();
    var c = function(){
        console.log("~")
    }
    // 上面的代码相当于是:
    var c;
    c();
    var c = function(){
        console.log("~")
    }
    

2.执行上下文

  1. 代码分类(位置)
    • 全局代码
    • 函数(局部)代码
  2. 全局执行上下文:
    • 在执行全局代码前将window确定为全局执行上下文
    • 对全局数据进行预处理
      • var定义的全局变量==》undefined,添加为window的属性
      • function声明的全局函数==》赋值(fun),添加为window的方法
      • this==》赋值(window)
    • 开始执行全局代码
  3. 函数执行上下文
    • 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(是一个虚拟对象,执行完后就被删除。换一个说法就是,在定义一个方法是,不会创建一个函数执行上下文对象,只有当调用函数时,才后创建一个函数执行上下文对象)
    • 对局部数据进行预处理
      • 形参变量==》赋值(实参)==》添加文执行上下文的属性
      • arguments==》赋值(实参列表),添加为执行上下文的属性
      • var定义的局部变量==》undefined,添加为执行上下文的属性
      • function声明的函数==》赋值(fun),添加为执行上下文的方法
      • this==》赋值(调用函数的对象)
    • 开始执行函数体代码

3.执行上下文栈

  1. 在全局代码执行前js引擎就会创建一个栈来存储管理所有的执行上下文对象
  2. 在全局执行上下文(window)确定)后,将window添加到栈中(压栈)
  3. 当开始执行一个函数时,将该函数执行上下文对象添加到栈中(压栈)
  4. 即使正在执行的函数里又有多个该函数执行上下文对象,都要按照顺序添加到栈中(压栈)中并执行
  5. 在当前函数执行完毕后,将栈顶的对象移除(出栈)
  6. 如此循环后(第三步开始),当所有的函数执行上下文对象执行完后,栈中只有window

4.面试题

console.log("gb:", i);
var i = 1;
foo(i);
function foo(i){
    if(i == 4) return;
    console.log("fb:" + i);
    foo(i + 1);	
    console.log("fe:" + i);
}
// 上面的代码中有几个上下为对象? 5
// 上面的代码的结果是什么?

// ----------------------------

function a(){}
var a;
console.log(a);
// 结果是什么?	结果为:"function"
// 实际上问的是变量提升和函数提升的问题,这两种提升到底是谁先提升。看结果得知,是先变量提升,后函数提升

// ----------------------------

if(!(b in window)){
    var b = 1;
}
console.log(b);
// 结果为  undefined
// 为什么?  还会变量提升问题

// ----------------------------

var c =1;
function c(c){
    console.log(c)
}
c(2);	// 报错,提示c不是一个function
//为什么会这样呢?这还是变量提升和函数提升问题,代码的实际执行时这样的:
var c;
function c(c){
    console.log(c)
}
c =1;
c(2);
// 先变量提升,但是变量还没赋值,接着函数提升,在变量赋值。所以最后c是变量

3、作用域域作用域链

  1. 理解

    • 作用域就是一块“地盘”,一个代码段所在的区域
    • 它是静态的(相对于上下文对象),在编写代码是就确定了
  2. 分类

    1. 全局作用域

    2. 函数作用域

    3. 没有快作用域(ES6有了)

      if(true){
          var a = 3;
      }
      console.log(a);		// 3
      
  3. 作用:

    1. 隔离变量,不同作用域下同名变量不会有冲突。

============

作用域与执行上下文:

区别1:

  • 全局作用域之外,每个函数都会创建自已的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时
  • 全局执行上下文环境是在全局作用域确定之后,j5代码马上执行之前创建
  • 函数执行上下文是在调用函数时,函数体代码执行之前创建

区别2:

  • 作用域是静态的只要函数定义好了就一直存在,且不会再变化
  • 执行上下文是动态的,调用函数时创建,函数调用结束时上下文环境就会被释放

联系:

  • 执行上下文(对象)是从属于所在的作用域
  • 全局上下文环境==>全局作用域
  • 函数上下文环境=>对应的函数使用域

============

作用域链:说白了,就是获取对象的顺序,从内到外。

4、闭包

最终理解:就是Java中类的get和set方法的应用

1.闭包的理解

1、任何产生闭包?
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。

2、闭包到底是什么?

  • 使用浏览器调试查看
  • 理解一:闭包是嵌套的内部函数(绝大部分人认为)
  • 理解二:包含是被引用变量(函数)的对象(极少数人认为)
  • 注意:闭包存在于嵌套的内部函数中

3、产生闭包的条件?

  • 函数嵌套
  • 内部函数引用了外部函数的数据(变量、函数)
function fun1(){
    var a = 2;
    var b = "abc";
    function fun2(){ // 执行函数定义,就会产生闭包(不用非得调用内部函数)
        console.log(a)
    }
}
fun1();

2.常用闭包

将函数作为另一个函数的返回值:

function fun1(){
    var a=2;
    function f(){
        a++;
        console.log(a);
    }
    return f;
}
var f = fun1();
f();	// 3
f();	// 4
// 从上面的例子中可以看出,闭包中应用的变量(函数)时没有关闭重新定义,而是保留着引用

将函数作为实参传递给另一个函数调用:

function showDelay(msg, time){
    setTimeout(function(){
        console.log(msg);
    }, time)
}
showDelay(23, 500)

3.闭包的作用

1.使用函数内部的变量在函数执行完成后,仍然存活在内存中(延长了局部变量的生命周期)

2.让函数外部可以操作(读写)到函数内部的数据(变量、函数)

问题:

  1. 函数执行完后,函数内部声明的局部变量(函数)是否还存在? 一般是不存在,存在于闭包的变量才可能存在。
  2. 在函数外部能直接访问函数内部的局部变量吗?不能,但是能通过闭包让外部操作
function fun1() {
    var a = 2;
    var b = "abc";

    function setA(x) {
        a = x;
        console.log(a);
    }
    function getA() {
        console.log(a);
        return a;
    }
    // test
    function test() {
        console.log(a);
        return a;
    }
    return {
        setA:setA,
        getA:getA
    };
}
var f = fun1();  // 在上面的函数中,有两个闭包(setA,getA),在函数fun1执行完后,函数中的变量一般都都会回收,但是只有且仅只有被闭包引用时才能存在。同时,函数fun1中的闭包也会被回收,只有当且仅当闭包被引用时,闭包才能存在而不被回收(未被引用的会被回收),而被闭包引用的变量延长生命周期。
f.getA()
f.setA(343)			
f.getA()
// 死亡
f = null;

4.闭包的生命周期

产生:在嵌套内部函数定义执行完成时就产生了(不是在调用)

死亡:在嵌套的内部函数成为垃圾对象时

5.闭包的应用

定义js模块:

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

方式一(普通方式引入模块)

一个js文件:test.js

function myModule() {
    var msg = "hello";

    function toUperCase() {
        console.log(msg.toUpperCase());
        // console.log(msg);
    }

    function toLowerCase() {
        console.log(msg.toLowerCase());
        // console.log(msg);
    }

    function setMsg(xxx) {
        msg = xxx;
        console.log(msg);
        console.log(this);
    }
    // 方式一
    return {
        toUperCase: toUperCase,
        toLowerCase: toLowerCase,
        setMsg:setMsg
    }
}

一个用于模块的html文件:test.html

<!DOCTYPE html>
<html>	<head>	</head>
    <body>
        <script src="./test.js"></script>
        <script>
            // 方式一:
            var module = myModule();
            module.toUperCase();
            module.toLowerCase();
            module.setMsg("1345");	
            module.toUperCase();
            module.toLowerCase();
        </script>
    </body>
</html>

方式二(立即执行函数式引入模块)

一个js文件:test.js

(function myModule(window) {
	var msg = "hello";

	function toUperCase() {
		console.log(msg.toUpperCase());
		// console.log(msg);
	}

	function toLowerCase() {
		console.log(msg.toLowerCase());
		// console.log(msg);
	}

	function setMsg(xxx) {
		msg = xxx;
		console.log(msg);
		console.log(this);
	}
	// 方式3二
	window.myModule2 = {
		toUperCase: toUperCase,
		toLowerCase: toLowerCase,
		setMsg: setMsg
	}
})(window)

一个用于模块的html文件:test.html

<script src="./闭包应用1.js"></script>
<script>
    // 方式二
    myModule2.toUperCase();
    myModule2.toLowerCase();
    myModule2.setMsg("1345");	
    myModule2.toUperCase();
    myModule2.toLowerCase();
</script>

6.闭包的缺点

缺点:

  • 函数执行完后,函数内的局部变量没有释放,占用内存时间会边长
  • 容易造成内存泄漏

解决:

  • 能不用闭包就不用
  • 及时释放

7.闭包最终理解题

<script>
    function fun(n, o){
        console.log(o);
        return {
            fun: function(m){
                return fun(m, n);
            }
        }
    }
    var a = fun(0);
    a.fun(1);
    a.fun(2);
    a.fun(3);
    // ------
    var b = fun(0).fun(1).fun(2).fun(3);
    // ------
    var c = fun(0).fun(1);
    c.fun(2);
    c.fun(3);
</script>

对象高级

1、对象创建模式

1.Object构造函数模式

  • 套路:先创建空Object对象,再动态添加属性/方法
  • 应用场景:起始时不确定对象内部数据
  • 问题:语句太多
var p = new Object();
p.name = "text";
p.age = 12;
p.....

2.对象字面量模式

  • 套路:使用{} 创建对象,同时指定属性/方法
  • 使用场景:起始时对象内部数据是确定的
  • 问题:如果创建多个对象,有重复代码
var p = {
    p.name = "text",
    p.age = 12,
    p.....
}

3.工厂模式

  • 套路:通过工厂函数动态创建对象并返回
  • 适用场景:需要创建多个对象
  • 问题:对象没有一个具体的类型,都是Object类型
<script>
    // 人的类型
    function createPerson(name, age) {
        return {
            name: name,
            age: age,
            setName: function(name) {
                this.name = name;
            }
        }
    }
    var p1 = createPerson("tom", 23);// ... 创建更多
    console.log(typeof p1)	// object

    // 学生的类型
    function createStudent(name, age) {
        return {
            name: name,
            age: age
        }
    }
    var s1 = createStudent("Low", 11);// ... 创建更多
    console.log(typeof s1) // object
</script>
// 通过上面可知,对象没有一个具体的类型,都是Object类型

4.自定义构造函数模式

  • 套路:自定义构造函数,通过new创建对象
  • 适用场景:需要创建多个类型确定的对象
  • 问题:每个对象都要相同的数据(每个对象的属性可能不同,但是方法是相同的),浪费内存
// 人的类型
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.setName = function(name){this.name = name};
}
var p1 = new Person("tom", 23);// ... 创建更多
console.log(typeof p1)	// Person

// 学生的类型
function Student(name, age) {
    this.name = name;
    this.age = age;
    this.setName = function(name){this.name = name};
}
var s1 = new Student("Low", 11);// ... 创建更多
console.log(typeof s1) // Student

5.构造函数+原型的组合模式

  • 套路:自定义构造函数,属性在函数中初始化(在构造函数中只初始化一般属性),方法添加到原型上
  • 使用场景:需要创建多个类型确定的对象
function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.setName = function(name) {
    this.name = name
};
var p1 = new Person("tom", 23); // ... 创建更多
console.log(p1 instanceof Person) // true
console.log(p1) // true

// 学生的类型
function Student(name, age) {
    this.name = name;
    this.age = age
}
Student.prototype.setName = function(name) {
    this.name = name
};
var s1 = new Student("Low", 11); // ... 创建更多
console.log(s1 instanceof Student) // true
console.log(s1) // true

2、继承模式

1.原型链继承

  • 套路:
    • 定义父类型构造函数
    • 给父类型的原型添加方法
    • 定义子类型的构造函数
    • 创建父类型的对象赋值给子类型的原型
    • 将子类型原型的构造属性设置为子类型
    • 给子类型原型添加方法
    • 创建子类型的对象:可以调用父类型的方法
  • 关键:子类型的原型为父类型的一个实例对象
// 父类型
function Supper(){
    this.supProp = "supper prototype"
}
Supper.prototype.showSupperProp = function(){
    console.log(this.supProp);
}

// 子类型
function Sub(){
    this.subProp = "subProp prototype"
}
// 子类型的原型为父类型的一个实例对象
Sub.prototype = new Supper();
// 将子类型原型的构造属性设置为子类型
Sub.prototype.constructor = Sub;
Sub.prototype.showSubProp =function (){
    console.log(this.subProp);
}
var sub = new Sub();
sub.showSupperProp();
sub.showSubProp();

2.借用构造函数继承

  • 套路
    • 定义父类型构造函数
    • 定义子类型的构造函数
    • 在子类型构造函数中调用父类型构造
  • 关键:在子类型构造函数中通用call() 调用父类型构造函数。
function Person(name, age){
    this.name = name;
    this.age = age;
}
function Student(name, age, price){
    Person.call(this, name, age);
    this.price = price;
}
var s1=new Student('通', 23, 442);
console.log(s1)

3.组合继承

原型链+借用构造函数的组合继承

  • 利用原型链实现对父类型对象的方法继承
  • 利用call() 基于父类型构造函数初始化相同的属性
function Person(name, age){
    this.name = name;
    this.age = age;
}
Person.prototype.setName = function(name){
    this.name = name;
}
function Student(name, age, price){
    Person.call(this, name, age);
    this.price = price;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
Student.prototype.setPrice = function(price){
    this.price = price;
}
var s1=new Student('通', 23, 442);
console.log(s1)

线程机制与事件机制

1、进程与线程

进程:程序的一次执行,它占有一片独有的内存空间;可以通过windows任务管理器查看进程。

线程:线程是进程内的一个独立执行单元,是程序执行的一个完整流程,是cpu的最小的调度单元

在这里插入图片描述

相关知识:

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

相关问题:

  • 何为多进程和多线程?
    • 多进程–一哥应用程序可以同时启动多个实例运行
    • 多线程—在一个进程内,同时又多个线程运行
  • 比较单线程与多线程?
    • 多线程
      • 优点:能有效提升CPU的利用率
      • 缺点:创建多线程开销、线程间切换开销、死锁与状态同步问题
    • 单线程
      • 优点(顺序编程简单易懂)、缺点(效率低)
  • js是单线程
  • 浏览器运行是多线程

2、浏览器内核

内核:支撑浏览器运行的最核心的程序

不同的浏览器可能内核不一样:

  • Chrome、Safari:webkit
  • FireFox:Gecko
  • IE:Trident
  • 360、搜狗等国内浏览器:Trident+webkit

内核由很多模块组成:
在这里插入图片描述

3、定时器引发的思考

在这里插入图片描述

4、js是单线程执行的

在这里插入图片描述

视频连接

5、浏览器的事件循环(轮询)模型

模型原理图:
在这里插入图片描述

相关重要概念:
在这里插入图片描述

在这里插入图片描述

6、H5 Web Workers(多线程)

在这里插入图片描述

注意:在分线程中的全局对象不再是window,所有在分线程中不可能更新界面

在这里插入图片描述

使用多线程:

<!DOCTYPE html>
<html>    <head>    </head>
    <body>
        <input type="text" placeholder="数值" id="number"/>
        <button id="bun">计算</button>
        <script>
            var input = document.getElementById("number");
            document.getElementById("bun").onclick = function(){
                var number = input.value;

                // 创建一个Worker对象。其中参数是一个js文件名路径名
                var worker = new Worker("worker.js");
                // 绑定接受消息的监听
                worker.onmessage = function (event){
                    console.log("主线程接收分线程返回的数据:", event.data)

                }
                // 向分线程发送信息
                worker.postMessage(number);
                console.log("主线程向分线程发送的数据:", number)
            }
        </script>
    </body>
</html>

被引用多线程的js文件

function fiboacci(n) {
	return n <= 2 ? 1 : fiboacci(n - 1) + fiboacci(n - 2);
}

//  这个格式要固定,不能使用函数声明
var onmessage = function (event){
	console.log("分线程接收主线程发送的数据:", event.data)
	var number = event.data;
	// 计算(自己定义的逻辑)
	var result = fiboacci(number);
	postMessage(result);
	console.log("分线程向主线程返回数据:", result)
}

// 注意:在分线程中的全局对象不再是window,所有在分线程中不可能更新界面

多线程的不知:

  • 不能跨域加载js
  • worker内代码不能访问DOM(更新UI)
  • 不是没个浏览器都支持这个新特性

补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值