前端学习<四>JavaScript——54-原型链

server/2024/9/23 10:24:39/

常见概念

  • 构造函数

  • 构造函数-扩展

  • 原型规则和示例

  • 原型链

  • instanceof

构造函数

任何一个函数都可以被 new,new 了之后,就成了构造方法。

如下:

 function Foo(name, age) {this.name = name;this.age = age;//retrun this;   //默认有这一行。new一个构造函数,返回一个对象}​var fn1 = new Foo('smyhvae', 26);var fn2 = new Foo('vae', 30); //new 多个实例对象

与普通函数相比,构造函数有以下明显特点:

  • 用 new 关键字调用。

  • 不需要用 return 显式返回值的,默认会返回 this,也就是新的实例对象。

  • 建议函数名的首字母大写,与普通函数区分开。

参考链接:

  • JavaScript 中的普通函数与构造函数

当 new 之后,this 会先变成一个空对象,然后通过this.name = name来赋值。

构造函数的扩展

上图中发现,数组、对象、函数也有构造函数,它们的构造函数是 Array、Object、function。实际开发中,都推荐前面的书写方式。

原型规则

原型规则是学习原型链的基础。原型规则有五条,下面来讲解。

规则 1

所有的引用类型(数组、对象、函数),都具有对象特性,都可以自由扩展属性。null 除外。

举例:

规则 2

所有的引用类型(数组、对象、函数),都有一个_proto_属性,属性值是一个普通的对象_proto_的含义是隐式原型。

其实,规则 2 是规则 1 的特例,只不过,js 语法帮我们自动加了 规则 2。

规则三

所有的函数(不包括数组、对象),都有一个prototype属性,属性值是一个普通的对象prototype的含义是显式原型。(实例没有这个属性)

规则四

所有的引用类型(数组、对象、函数),_proto_属性指向它的构造函数prototype值。

总结:以上四条,要先理解清楚,然后再来看下面的第五条。

规则五

当试图获取一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_中寻找(即它的构造函数的prototype)。

举例代码1

 //创建方法function Foo(name) {this.name = name;}​Foo.prototype.alertName = function () {// 既然 Foo.prototype 是普通的对象,那也允许给它添加额外的属性 alertNameconsole.log(this.name);};​var fn = new Foo('smyhvae');fn.printName = function () {console.log(this.name);};​// 测试fn.printName(); //输出结果:smyhvaefn.alertName(); //输出结果:smyhvae

上方代码中,虽然 alertName 不是 fn 自身的属性,但是会从它的构造函数的prototype里面找。

扩展:遍历循环对象自身的属性

我们知道,for in循环可以遍历对象。针对上面的那个 fn 对象,它自身有两个属性:nameprintName,另外从原型中找到了第三个属性alertName。现在,如果我们对 fn 进行遍历,能遍历到两个属性还是三个属性呢?

答案:两个。因为,高级浏览器中已经在 for in循环中屏蔽了来自原型的属性。但是,为了保证代码的健壮性,我们最好自己加上判断,手动将第三个属性屏蔽掉:

 for (var item in fn) {if (fn.hasOwnProperty(item)) {console.log(item);}}

原型链

还是拿上面的举例代码1举例,如果此时在最后面加一行代码:

     fn.toString();   //去 fn._proto_._proto_ 中查找 toString()方法

上面的代码中,fn 直接调用了 toString()方法,这是因为它通过原型链,去_proto__proto_里找到了Object,而Object是由toString()方法的。

instanceof

格式:

 对象 instanceof 构造函数;

instanceof的作用:用于判断引用类型属于哪个构造函数

例 1:判断一个变量是否为数组: 变量 instanceof Array

例 2:

 function Person() {}​//p--->Person.prototype--->Object.prototype--->nullvar p = new Person();//构造函数的**原型**是否在 p 对象的原型链上!console.log(p instanceof Person);

例 3:

 fn instanceof Foo;

上面这句话,判断逻辑是:fn 的_proto_一层一层往上找,看能否对应到 Foo.prototype

原型链如下:(重要)

注意,Object 这个构造方法的显式原型是 null,这是一个特例。

issues 101 补充:通过原型链查找时,如果你找的是一个属性的话,则返回 undefined,如果你找的是一个方法,则报错。

常见题目

  • 如何准确判断一个变量是数组类型

  • 写一个原型链继承的例子

  • 描述 new 一个对象的过程

  • zepto(或其他框架)源码中如何使用原型链

下面分别讲解。

题目一:如何准确判断一个变量是数组类型

答案:

 var arr1 = [];​console.log(arr1 instanceof Array); //打印结果:true。console.log(typeof arr1); //打印结果:object。提示:typeof 方法无法判断是否为数组

上方代码表明,只能通过 instanceof 来判断是否为数组。而 typeof 的打印结果是 object。

题目二:写一个原型链继承的例子

来看个基础的代码:

上面这个例子是基础,但是,在回答面试官的问题时,不要写上面的例子。要写成下面这个例子:(更贴近实战)

function DomElement(id) {this.dom = document.getElementById(id);
}
DomElement.prototype.html = function (val) {var ele = this.dom;if (val) {ele.innerHTML = val;return this;} else {return ele.innerHTML;}
};
DomElement.prototype.on = function (type, fn) {var ele = this.dom;ele.addEventListener(type, fn);return this;
};
var div1 = new DomElement('div1');
div1.html('<p>这是一段文字</p >');
div1.on('click', function () {console.log('clicked');
});

题目三:描述 new 一个对象的过程

(1)创建一个新对象

(2)this 指向这个新对象

(3)执行代码(对 this 赋值)

(4)返回 this

参考链接:

  • 原型、原型链、继承模式

写在最后:希望大家可以点个关注点个赞,这对up真的很重要!谢谢! 

http://www.ppmy.cn/server/19994.html

相关文章

react 遇到的问题1 ——( 数据更新视图没更新)已解决

问题&#xff1a; 使用react开发项目时&#xff0c;使用useState 定义数据&#xff0c;通过定义的set方法修改数据&#xff0c;视图没有更新 原因&#xff1a; 在 React 中使用 useState 定义数据时&#xff0c;useState 返回一个数组&#xff0c;包含当前状态和更新的函数。…

【学习】软件测试自动化,是未来的趋势还是当前的必需

在当今快速迭代的软件开发周期中&#xff0c;速度和质量成为了企业生存的关键。随着DevOps实践的普及和持续集成/持续部署&#xff08;CI/CD&#xff09;流程的标准化&#xff0c;软件测试自动化已经从未来的趋势转变为当前的必要性。本文将探讨自动化测试的现状、必要性以及其…

ICCV 2021 | FcaNet: Frequency Channel Attention Networks 中的频率分析

ICCV 2021 | FcaNet: Frequency Channel Attention Networks 中的频率分析 论文&#xff1a;https://arxiv.org/abs/2012.11879代码&#xff1a;https://github.com/cfzd/FcaNet 文章是围绕 2D 的 DCT 进行展开的&#xff0c;本文针对具体的计算逻辑进行梳理和解析。 f ( u ,…

笔记:.NET的框架梳理及相关概念了解(“.NET Core“ “.NET“ “.NET Framework“)

一、.NET设计 架构&#xff1a;C/C程序是直接将源码编译成机器码&#xff08;CPU可以识别和运行的指令&#xff09;&#xff0c;对于不同CPU&#xff0c;其指令集不同&#xff0c;机器码也就不同&#xff0c;故&#xff1a;C/C程序编译时&#xff0c;需选择具体的CPU架构&…

深度学习基础:循环神经网络中的长期依赖问题

循环神经网络中的长期依赖问题 在深度学习中&#xff0c;循环神经网络&#xff08;RNN&#xff09;是一种经典的模型&#xff0c;用于处理序列数据&#xff0c;如自然语言处理、时间序列预测等任务。然而&#xff0c;传统的RNN存在着一个长期依赖问题&#xff0c;即在处理长序…

linux demo

1.1&#xff09;if case test the results #!bin/bash read -p “请输入你的成绩&#xff1a;” num if [ $num -ge 0 ] && [ $num -le 100 ];then if [ $num -ge 80 ] && [ $num -le 100 ];then echo “成绩优秀” elif [ $num -ge 60 ] && [ $num …

redis单线程模型

工作原理 在Redis中&#xff0c;当两个客户端同时发送相同的请求时&#xff0c;Redis采用单线程模型来处理所有的客户端请求&#xff0c;会依次处理这些请求&#xff0c;每个请求都会按照先后顺序被执行&#xff0c;不会同时处理多个请求。使得Redis能够避免多线程并发访问数据…

element-plus 如何获取所有的icon图标名称,并排列展示?

一、获取所有的element-plus中icon图标&#xff1a; import * as ElIcon from element-plus/icons-vueconsole.log(ElIcon) 从控制台打印可以看到&#xff0c;ElIcon为所有的icon组成的对象&#xff0c;要组成包含icon名称的数组&#xff0c;可以去key值或者name值&#xff08…