关于构造函数和原型链运行机制的试题与知识点总结

2024-08-22 03:58

本文主要是介绍关于构造函数和原型链运行机制的试题与知识点总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:

  • 如何准确判断一个变量是数组类型
  • 写一个原型链继承的例子
  • 描述new一个对象的过程
  • zepto(或其他框架)源码中如何使用原型链

知识点:

1. 构造函数

  • 构造函数要用大写字母开头
  • var a=其实是var a=new Object)的语法糖
  • var a=[]其实是var a=new Array)的语法糖
  • function Foo){…}其实是var Foo=new Function(.)
  • 使用instanceof 可以判断一个函数是否是一个变量的构造函数

a71efaafly1g2rc6awjmxj20mf0dzwhx.jpg

2. 原型规则和示例

  • 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null"意外)
  • 所有的引用类型(数组、对象、函数),都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
  • 所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通的对象
  • 所有的引用类型(数组、对象、函数),_proto_属性值指向它的构造函数的"prototype"属性值

a71efaafly1g2rchgklygj20mg0e4dk5.jpg

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

    我们在一个构造函数的显式原型上去定义方法可以有效的减少内存占用,因为如果我们定义在构造函数内部,则每实例化一个对象,就会开辟一个堆内存去存放挂载到其实例上,然而对于方法的调用这是没有必要的

关于 prototype 它有以下几个要点,务必牢记:

  1. 每一个函数(类)都有原型属性,称作prototype,这个属性提供了可供当前类的实例调用的属性和方法。
  2. 浏览器默认给原型开辟的堆内存中有一个constructor属性,这个属性存放的是函数本身
  3. 每一个对象的实例上都有一个__proto__属性称为原型链,这个属性指向当前类的所属原型,不确定的原型都指向Object.prototype,然而Object的__proto__指向null

prototype下的name属性指函数名,length属性指传入的形参的个数

a71efaafly1g2rcm3gp5cj20me0e377t.jpg

利用 for in 循环可以来获取对象身上自己定义的属性而不获取来自原型的属性

a71efaafly1g2rcrpqiwvj20mk0e0tbu.jpg

3. 原型链

当一个方法在原型上没有时,就会查找原型链

a71efaafly1g2rcwekrs7j20mj0du0vy.jpg
a71efaafly1g2rd0r86dzj20mm0drmyo.jpg

4. intanceof

intanceof 用于判断 引用类型 属于哪个 构造函数 的方法。

finstanceofFoo的判断逻辑是:

  1. f的__proto__一层一层往上,能否对应到Foo.prototype,只要 f.__proto__ == Foo.prototype 就验证通过
  2. 再试着判断 f instanceof Object
function Foo(name) {this.name = name
}
function Foo2() { }var f = new Foo('蔡徐坤');// 让Foo2的prototype指向Foo的prototype,这时候,Foo2与Foo的prototype可以看作为一个对象,也就是说修改Foo的prototype相当于修改Foo1的prototype,反之亦然
Foo2.prototype = Foo.prototype;
Foo.prototype.age = 'unknown';
Foo2.prototype.hobbies = '唱、跳、篮球、Rap';// 由下可以看出Foo2与Foo的prototype指向同一个对象
console.log(Foo.prototype); // Foo { age: 'unknown', hobbies: '唱、跳、篮球、Rap' }
console.log(Foo2.prototype); //Foo { age: 'unknown', hobbies: '唱、跳、篮球、Rap' }// 由于实例 f 的 __proto__ 指向 Foo 的 prototype ,而Foo的 prototype 与 Foo2 的 prototype 是一个,所以 f 既属于 Foo 又属于 Foo2
console.log(f instanceof Foo); // true
console.log(f instanceof Foo2); // true

5. 关于原型重定向问题

先看下面的一个例子:

function fun(){this.a = 0;this.b = function(){alert(this.a);}
}
fun.prototype = {b: function(){this.a = 20;alert(this.a);},c: function(){this.a = 30;alert(this.a);}
}
var my_fun = new fun();
my_fun.b(); // 0
my_fun.c(); // this => my_fun.a = 30 ; 30

结果:0 30

my_fun.a 用来设置私有属性

my_fun.__proto__.a 用来设置公有属性

原型重定向导致的问题:

  1. 自己开辟的堆内存中没有constructor属性,导致类的原型构造函数缺失(解决:自己手动在堆内存中增加constructor属性)
  2. 当原型重定向后,浏览器默认开辟的那个类原型堆内存会被释放掉,如果之前已经存储了一些方法或属性,都会丢失(所以:内置累的原型不允许重定向到自己开辟的堆内存,因为内置类的原型上存在很多属性方法,重定向后都没了,这样是不被允许的;但浏览器对内置类有保护机制)
  3. 当我们需要给类的原型批量设置属性和方法的时候,一般都是让原型重定向到自己创建的对象中

解题:

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

var arr = [];
console.log(arr instanceof Array); // true
console.log(typeof arr); // object 不能用typeof判断一个变量是否是数组类型

2. 写一个原型链继承的例子

基础实例:

//动物
function Animal(){this.eat = function(){console.Log('animal eat')}
}
//狗
function Dog(){this.bark = function(){console.Log('dog bark')}
}
Dog.prototype = new Animal()
//哈士奇
var hashiqi = new Dog()
//接下里代码演示时,会推荐更加贴近实战的原型继承示例!

封装DOM查询:戳我查看完整示例代码

function Elem(id) {this.elem = document.getElementById(id);
}Elem.prototype.html = function (html) {if (html == null) {return this.elem.innerHTML;} else {this.elem.innerHTML = html;return this; // 返回this,便于链式操作}
}Elem.prototype.on = function (eventType, fn) {if (eventType != null && fn != null) {this.elem.addEventListener(eventType, fn);return this;} else {throw new Error('请传入“事件类型”,“执行方法”!');}
}var div = new Elem('div');
div.on('click', function(){alert(div.html());
})

3. 描述new一个对象的过程

  • 创建一个新对象
  • this 指向这个新对象
  • 执行代码,即对this 赋值
  • 返回 this (这一步是默认的)

这篇关于关于构造函数和原型链运行机制的试题与知识点总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095175

相关文章

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi