JavaScript高阶 day-04

目录

一.什么是原型,什么是原型链?

[二.call / apply / bind 有啥区别](#二.call / apply / bind 有啥区别)

三.JS四种检测数据类型的方式

四.说说继承

五.for..in和for..of和forEach的区别

六.forEach和map方法的区别

[七. js高阶中数组的常用的操作方法](#七. js高阶中数组的常用的操作方法)

八.什么是严格模式

九.什么是高阶函数?

十.闭包是什么,有什么特性,对页面有什么影响

十一.浅拷贝与深拷贝

十二.赋值(地址传递)和浅拷贝的区别

[十三.构造函数 和 class的区别](#十三.构造函数 和 class的区别)

十四.栈内存和堆内存的区别?


一.什么是原型,什么是原型链?

原型: 每一个构造函数,都会有一个 prototype 属性。该属性指向一个对象,该对象称之为 原型对象,即原型。

原型链: 当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的 __proto__ 上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的 __proto__ 中查找(即上一层构造函数的prototype),这样一层一层向上查找直到Object的prototype结束,这样就会形成一个链式结构,我们称为原型链。我们可以说:它们是继承关系

二.call / apply / bind 有啥区别

call: call(thisObj, arg1, arg2...)

要求传入函数的参数是参数列表

apply: apply(thisObj, argArray)

要求传入函数的参数必须放入数组中整体传入

bind:bind(thisObj,arg1,arg2,...)

  • 共同点 : 都可以改变this指向

  • 不同点:

    • call 和 apply会立即调用函数.bind不会立即调用函数, 需要手动调用.

    • call及bind 和 apply传递的参数不一样,call及bind传递参数使用逗号隔开,apply使用数组传递.

  • 应用场景
    1. call 经常做继承.

    2. apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值

    3. bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.

三.JS四种检测数据类型的方式

1.typeOf :只能检测基本数据类型 2.instanceOf :检测当前实例是否属于某个类的方法 3.constructor: 检测当前实例的构造函数 4.Object.prototype.toString.call( ) : 最准确的方式;

四.说说继承

  1. 构造函数继承(在子类的构造函数中执行父类的构造函数,并为其绑定子类的this,让父类的构造函数把成员属性和方法都挂到子类的this上) 缺点:无法访问原型上的方法

  2. 原型链继承(将子构造函数的原型对象指向父构造函数的实例,让constructor 重新指向子构造函数) 缺点:无法为不同的实例初始化继承来的属性

  3. 组合式继承(将原型链继承和构造函数继承组合到一起, 综合了原型链继承和构造函数继承的优点) 缺点:调用了两次父类构造函数

  4. 原型式继承(Object.create():这个方法接收两个参数:一是用作新对象原型的对象、二是为新对象定义额外属性的对象(可选参数),核心思想:使用一个中间函数,连接父类与子类的关系。借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。)

  5. extends继承(class和extends是es6新增的,class创建一个类,extends实现继承)

可参照文档:JS中常用实现继承的方法(Object.create的原理)_object.create原理-CSDN博客

五.for..in和for..of和forEach的区别

  • for ..in:
  1. 可以循环数组也能循环对象,循环遍历的值是数据结构的键值;
  2. 可以使用return、break、continue中断循环;
  3. 在有些情况下会以随机顺序遍历数组,所以最好用来遍历对象;
  • for ..of:
  1. 可以循环可迭代对象(如数组、字符串等),循环遍历的值是数据结构的值;
  2. 可以使用return、break、continue中断循环;
  • forEach:
  1. 在回调函数内部有三个参数:item、index、arr分别表示当前项、当前项的索引下标、数组本身;
  2. 会对数组的每一个元素执行一次提供的函数,不改变原数组、没有返回值(undefined);

六.forEach和map方法的区别

相同点

1、都是循环遍历数组中的每一项

2、forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是value(当前每一项)、index(索引值)、array(原数组)

3、匿名函数中的this都是指向window

4、只能遍历数组

区别

1、forEach()返回值是undefined,

2、map()返回一个新数组

七. js高阶中数组的常用的操作方法

复制代码
● arr.forEach(function(){}):遍历数组
● arr.map(function(){}):对数组遍历并操作数组元素,返回操作后元素组成的新数组
● arr.filter(function({}));对数组元素进行过滤,返回符合元素组成的新数组
● arr.find(function(){}):查找数组中符合的元素
● arr.some(function){}):对数组的元素进行判断是否有符合的元素
● arr.every(function){}):对数组的元素进行判断是否全部符合
● arr.find(function){})方法返回符合查找条件的第一个数组元素的值。
● arr.reduce(function(total,value,index,array){},initialValue):方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

八.什么是严格模式

JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性 JavaScript变体的一种方式,即在严格的条件下运行 JS 代码。

严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。

设立严格模式的原因:

1、消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;

2、消除代码运行的一些不安全之处,保证代码运行的安全;

3、提高编译器效率,增加运行速度;

4、为未来新版本的Javascript做好铺垫。

严格模式下的语法变化:

  • 不能不声明变量直接使用

  • 函数的this指向,指向undefined

  • 函数的参数,不可以重名

  • 构造函数如果不使用new实例化,会报错

九.什么是高阶函数?

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

只需满足以下任意一个条件,即是高阶函数:

\1. 接受一个或多个函数作为输入 \2. return 返回另外一个函数

十.闭包是什么,有什么特性,对页面有什么影响

**概念:**内部函数访问其所在的外部函数中声明的参数和变量,形成的词法环境叫闭包.

闭包有三个特性:

  • 1、函数嵌套函数

  • 2、函数内部访问外部函数的参数或变量

  • 3、可以使函数中的变量可以长期驻扎在内存

使用闭包的好处:

  • 1、变量长期驻扎在内存中

  • 2、避免全局变量的污染(多人定义同样名字的全部变量冲突)

  • 3、私有成员的存在

使用闭包的坏处:

  • 1、常驻内存

  • 2、会增大内存的使用量

  • 3、使用不当会造成内存泄露

注意:内存泄露:指的是**应用程序不再用到的内存,由于某些原因,没有及时释放,就叫做内存泄漏。**

会造成内存泄漏的js操作:

1.意外的全局变量

2.未清理的DOM元素的引用

3.被遗忘的定时器或者回调函数

4.闭包

5.过多的console.log语句

十一.浅拷贝与深拷贝

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

浅拷贝: 只复制指向某个对象的指针**而不复制对象本身,新旧对象还是共享同一块内存。**

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

深拷贝:**会另外创建一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。**

深拷贝的实现方式

1.JSON.parse(JSON.stringify())

原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

2.手写递归方法

递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝;

十二.赋值(地址传递)和浅拷贝的区别

  • 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

  • 浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即:默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

十三.构造函数 和 class的区别

构造函数:

  1. 在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数。构造函数首字母一般大写

  2. 功能类似对象模板,一个构造函数可以生成任意多个实例,实例对象具有相同的属性、行为特征,但不相等。

  3. 函数体内使用 this,引用将要生成的实例对象。

  4. 必需使用 new 命令调用函数,生成实例对象。

class类:

  1. 类不存在变量提升(hoist),

  2. 类的方法内部如果含有this,它默认指向类的实例,

  3. 类使用extends来继承,

  4. 类的数据类型就是函数,类本身就指向构造函数;使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致;

十四.栈内存和堆内存的区别?

栈(stack):由编译器自动分配释放,存放函数的参数值,局部变量等;

堆(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统释放。

了解以下内容

1、栈:基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。 优点:相比于堆来说存取速度会快,并且栈内存中的数据是可以共享的,例如同时声明了var a = 1和var b = 1,会先处理a,然后在栈中查找有没有值为1的地址,如果没有就开辟一个值为1的地址,然后a指向这个地址,当处理b时,因为值为1的地址已经开辟好了,所以b也会同样指向同一个地址。 缺点:相比于堆来说的缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

2、堆:堆内存中的对象不会随方法的结束而销毁,就算方法结束了,这个对象也可能会被其他引用变量所引用(参数传递)。创建对象是为了反复利用(因为对象的创建成本通常较大),这个对象将被保存到运行时数据区(也就是堆内存)。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

相关推荐
小陈同学呦2 小时前
前端如何处理订单状态导航的数据竞态问题
前端·javascript
开发者每周简报2 小时前
网海三部曲·无名宗师传
javascript·人工智能
isyangli_blog2 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008112 小时前
FastAPI APIRouter
开发语言·python
Benszen2 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆2 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木2 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充3 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~3 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball6163 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang