【面试题】 JavaScript基础面试笔记整理

本文涉及的产品
应用实时监控服务-用户体验监控,每月100OCU免费额度
应用实时监控服务-应用监控,每月50GB免费额度
简介: 【面试题】 JavaScript基础面试笔记整理

JavaScript 重点知识

了解构造函数原型对象的语法特征,掌握 JavaScript 中面向对象编程的实现方式,基于面向对象编程思想实现 DOM 操作的封装。

  • 了解面向对象编程的一般特征
  • 掌握基于构造函数原型对象的逻辑封装
  • 掌握基于原型对象实现的继承
  • 理解什么原型链及其作用
  • 能够处理程序异常提升程序执行的健壮性

一、面向对象

学习 JavaScript 中基于原型的面向对象编程序的语法实现,理解面向对象编程的特征。

面向对象编程是一种程序设计思想,它具有 3 个显著的特征:封装、继承、多态。

1.1 封装

封装的本质是将具有关联的代码组合在一起,其优势是能够保证代码复用且易于维护,函数是最典型也是最基础的代码封装形式,面向对象思想中的封装仍以函数为基础,但提供了更高级的封装形式。

命名空间

先来回顾一下以往代码封装的形式:

<script>
  // 普通对象(命名空间)形式的封装
  let beats = {
    name: '狼',
    setName: function (name) {
      this.name = this.name;
    },
    getName() {
      console.log(this.name);
    }
  }
  beats.setName('熊');
  beats.getName();
</script>
复制代码

以往以普通对象(命名空间)形式封装的代码只是单纯把一系列的变量或函数组合到一起,所有的数据变量都被用来共享(使用 this 访问)。

构造函数

对比以下通过面向对象的构造函数实现的封装:

<script>
  function Person() {
    this.name = '佚名';
    // 设置名字
    this.setName = function (name) {
      this.name = name;
    }
    // 读取名字
    this.getName = () => {
      console.log(this.name);
    }
  }
  // 实例对像,获得了构造函数中封装的所有逻辑
  let p1 = new Person();
  p1.setName('小明');
  console.log(p1.name);
  // 实例对象
  let p2 = new Person();
  console.log(p2.name);
</script>
复制代码

同样的将变量和函数组合到了一起并能通过 this 实现数据的共享,所不同的是借助构造函数创建出来的实例对象之间是彼此不影响的。

总结:

  1. 构造函数体现了面向对象的封装特性
  2. 构造函数实例创建的对象彼此独立、互不影响
  3. 命名空间式的封装无法保证数据的独立性

注:可以举一些例子,如女娲造人等例子,加深对构造函数的理解。

原型对象

实际上每一个构造函数都有一个名为 prototype 的属性,译成中文是原型的意思,prototype 的是对象类据类型,称为构造函数的原型对象,每个原型对象都具有 constructor 属性代表了该原型对象对应的构造函数。

<script>
  function Person() {
  }
  // 每个函数都有 prototype 属性
  console.log(Person.prototype);
</script>
复制代码

了解了 JavaScript 中构造函数与原型对象的关系后,再来看原型对象具体的作用,如下代码所示:

<script>
  function Person() {
    // 此处未定义任何方法
  }
  // 为构造函数的原型对象添加方法
  Person.prototype.sayHi = function () {
    console.log('Hi~');
  }
  // 实例化
  let p1 = new Person();
  p1.sayHi(); // 输出结果为 Hi~
</script>
复制代码

构造函数 Person 中未定义任何方法,这时实例对象调用了原型对象中的方法 sayHi,接下来改动一下代码:

<script>
  function Person() {
    // 此处定义同名方法 sayHi
    this.sayHi = function () {
      console.log('嗨!');
    }
  }
  // 为构造函数的原型对象添加方法
  Person.prototype.sayHi = function () {
    console.log('Hi~');
  }
  let p1 = new Person();
  p1.sayHi(); // 输出结果为 嗨!
</script>
复制代码

构造函数 Person 中定义与原型对象中相同名称的方法,这时实例对象调用则是构造函中的方法 sayHi

通过以上两个简单示例不难发现 JavaScript 中对象的工作机制:当访问对象的属性或方法时,先在当前实例对象是查找,然后再去原型对象查找,并且原型对象被所有实例共享。

<script>
    function Person() {
    // 此处定义同名方法 sayHi
    this.sayHi = function () {
      console.log('嗨!' + this.name);
    }
  }
  // 为构造函数的原型对象添加方法
  Person.prototype.sayHi = function () {
    console.log('Hi~' + this.name);
  }
  // 在构造函数的原型对象上添加属性
  Person.prototype.name = '小明';
  let p1 = new Person();
  p1.sayHi(); // 输出结果为 嗨!
  let p2 = new Person();
  p2.sayHi();
</script>
复制代码

总结:结合构造函数原型的特征,实际开发重往往会将封装的功能函数添加到原型对象中。

1.2 继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承的特性。

龙生龙、凤生凤、老鼠的儿子会打洞描述的正是继承的含义,分别封装中国人和日本人的行为特征来理解编程中继承的含义,代码如下:

<script>
  // 封装中国人的行为特征
  function Chinese() {
    // 中国人的特征
    this.arms = 2;
    this.legs = 2;
    this.eyes = 2;
    this.skin = 'yellow';
    this.language = '中文';
    // 中国人的行为
    this.walk = function () {}
    this.sing = function () {}
    this.sleep = function () {}
  }
  // 封装日本人的行为特征
  function Japanese() {
    // 日本人的特征
    this.arms = 2;
    this.legs = 2;
    this.eyes = 2;
    this.skin = 'yellow';
    this.language = '日文';
    // 日本人的行为
    this.walk = function () {}
    this.sing = function () {}
    this.sleep = function () {}
  }
</script>
复制代码

其实我们都知道无论是中国人、日本人还是其它民族,人们的大部分特征是一致的,然而体现在代码中时人的相同的行为特征被重复编写了多次,代码显得十分冗余,我们可以将重复的代码抽离出来:

原型继承

基于构造函数原型对象实现面向对象的继承特性。

<script>
  // 所有人
  function Person() {
    // 人的特征
    this.arms = 2;
    this.legs = 2;
    this.eyes = 2;
    // 人的行为
    this.walk = function () {}
    this.sing = function () {}
    this.sleep = function () {}
  }
  // 中国人
  function Chinese() {
    this.skin = 'yellow';
    this.language = '中文';
  }
  // 日本人
    function Japanese() {
    this.skin = 'yellow';
    this.language = '日文';
  }
</script>
复制代码

上述代码可以理解成将 ChineseJapanese 共有的属性和方法提取出来了,也就是说 ChineseJapanese 需要【共享】一些属性和方法,而原型对象的属性和方法恰好是可以被用来共享的,因此我们看如下代码:

<script>
  // 中国人
  function Chinese() {
    this.skin = 'yellow';
    this.language = '中文';
  }
  // 日本人
    function Japanese() {
    this.skin = 'yellow';
    this.language = '日文';
  }
  // 人们【共有】的行为特征
  let people = {
    // 人的特征
    arms: 2,
    legs: 2,
    eyes:2,
    // 人的行为
    walk: function () {},
    sleep: function () {},
    sing: function () {}
  }
  // 为 prototype 重新赋值
  Chinese.prototype = people;
  Chinese.prototype.constructor = Chinese;
</script>
复制代码

如下图所示:

创建对象 people 将公共的的属性和方法独立出来,然后赋值给构造函数的 prototype 这样无论有多少个民族都可以共享公共的属性和方法了:

<script>
  // 人们【共有】的行为特征
  let people = {
    // 人的特征
    arms: 2,
    legs: 2,
    eyes:2,
    // 人的行为
    walk: function () {},
    sleep: function () {},
    sing: function () {}
  }
  // 中国人
  function Chinese() {
    this.skin = 'yellow';
    this.language = '中文';
  }
  // 日本人
    function Japanese() {
    this.skin = 'yellow';
    this.language = '日文';
  }
  function Englist() {
    this.skin = 'white';
    this.language= '英文';
  }
  // 中国人
  Chinese.prototype = people;
  Chinese.prototype.constructor = Chinese;
  let c1 = new Chinese();
  // 日本人
  Japanese.prototype = people;
  Janpanese.prototype.constructor = Japanese;
  // 英国人
  English.prototype = people;
  English.prototype.constructor = English;
  // ...
</script>
复制代码

继承是一种可以“不劳而获”的手段!!!上述代码中 ChineseJapaneseEnglish 都轻松的获得了 people 的公共的方法和属性,我们说 ChineseJapaneseEnglish 继承了 people

上述代码中是以命名空间的形式实现的继承,事实上 JavaScript 中继承更常见的是借助构造函数来实现:

<script>
  // 所有人
  function Person() {
    // 人的特征
    this.arms = 2;
    this.legs = 2;
    this.eyes = 2;
    // 人的行为
    this.walk = function () {}
    this.sing = function () {}
    this.sleep = function () {}
  }
  // 封装中国人的行为特征
  function Chinese() {
    // 中国人的特征
    this.skin = 'yellow';
    this.language = '中文';
  }
  // 封装日本人的行为特征
  function Japanese() {
    // 日本人的特征
    this.skin = 'yellow';
    this.language = '日文';
  }
  // human 是构造函数 Person 的实例
  let human = new Person();
  // 中国人
  Chinese.prototype = human;
  Chinese.prototype.constructor = Chinese;
  // 日本人
  Japanese.prototype = human;
  Japanese.prototype.constructor = Japanese;
</script>
复制代码

如下图所示:

原型链

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链,

<script>
  // Person 构造函数
  function Person() {
    this.arms = 2;
    this.walk = function () {}
  }
  // Person 原型对象
  Person.prototype.legs = 2;
  Person.prototype.eyes = 2;
  Person.prototype.sing = function () {}
  Person.prototype.sleep = function () {}
  // Chinese 构造函数
  function Chinese() {
    this.skin = 'yellow';
    this.language = '中文';
  }
  // Chinese 原型对象
  Chinese.prototype = new Person();
  Chinese.prototype.constructor = Chinese;
  // 实例化
  let c1 = new Chinese();
  console.log(c1);
</script>
复制代码

在 JavaScript 对象中包括了一个非标准备的属性 __proto__ 它指向了构造函数的原型对象,通过它可以清楚的查看原型对象的链状结构。

 

给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:前端面试题库

相关实践学习
通过云拨测对指定服务器进行Ping/DNS监测
本实验将通过云拨测对指定服务器进行Ping/DNS监测,评估网站服务质量和用户体验。
相关文章
|
1月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
43 0
|
2月前
|
JSON JavaScript 前端开发
Javascript基础 86个面试题汇总 (附答案)
该文章汇总了JavaScript的基础面试题及其答案,涵盖了JavaScript的核心概念、特性以及常见的面试问题。
55 3
|
2月前
|
前端开发 JavaScript
JavaScript 面试系列:如何理解 ES6 中 Generator ?常用使用场景有哪些?
JavaScript 面试系列:如何理解 ES6 中 Generator ?常用使用场景有哪些?
|
3月前
|
JavaScript 前端开发
常见的JS面试题
【8月更文挑战第5天】 常见的JS面试题
61 3
|
20天前
|
JSON JavaScript 前端开发
[JS]面试官:你的简历上写着熟悉jsonp,那你说说它的底层逻辑是怎样的?
本文介绍了JSONP的工作原理及其在解决跨域请求中的应用。首先解释了同源策略的概念,然后通过多个示例详细阐述了JSONP如何通过动态解释服务端返回的JavaScript脚本来实现跨域数据交互。文章还探讨了使用jQuery的`$.ajax`方法封装JSONP请求的方式,并提供了具体的代码示例。最后,通过一个更复杂的示例展示了如何处理JSON格式的响应数据。
29 2
[JS]面试官:你的简历上写着熟悉jsonp,那你说说它的底层逻辑是怎样的?
|
20天前
|
自然语言处理 JavaScript 前端开发
[JS]同事看了我做的this笔记,直摇头,坦言:我还是参考启发博文吧
本文介绍了JavaScript中`this`关键字的重要性和使用规则。作者回顾了早期笔记,总结了`this`指向的各种情况,并分享了最新的理解。文章强调了`this`在不同上下文中的指向,包括对象方法、全局函数、箭头函数等,并提供了改变`this`指向的方法。适合JavaScript开发者参考。
38 2
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
432 37
|
2月前
|
JavaScript 前端开发 Java
JavaScript笔记(回顾一,基础知识篇)
JavaScript基础知识点回顾,包括语言定义、ECMAScript规范、字面量、变量声明、操作符、关键字、注释、流程控制语句、数据类型、类型转换和引用数据类型等。
JavaScript笔记(回顾一,基础知识篇)
|
2月前
|
存储 Java 关系型数据库
学成在线笔记+踩坑(0)——面试问题
介绍你的项目、项目难点、表是怎么设计的?、断点续传是怎么做的?、如何保证任务不重复执行? 、任务幂等性如何保证、分布式锁的三种实现方式
学成在线笔记+踩坑(0)——面试问题
|
1月前
|
Web App开发 JavaScript 前端开发
前端Node.js面试题
前端Node.js面试题
下一篇
无影云桌面