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

相关推荐
海阔天空_20132 分钟前
Python pyautogui库:自动化操作的强大工具
运维·开发语言·python·青少年编程·自动化
天下皆白_唯我独黑9 分钟前
php 使用qrcode制作二维码图片
开发语言·php
夜雨翦春韭13 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
小远yyds14 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
何曾参静谧27 分钟前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
q567315231 小时前
在 Bash 中获取 Python 模块变量列
开发语言·python·bash
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono