热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javascript的继续你相识若干?

什么是继续?大多数人运用继续不外乎是为了取得这两点优点,代码的笼统和代码的复用。代码的笼统就不用说了,交通东西和汽车这类的例子不可胜数,在传统的OO语言中(比如Java),代码的笼

什么是继续?

大多数人运用继续不外乎是为了取得这两点优点,代码的笼统和代码的复用。

代码的笼统就不用说了,交通东西和汽车这类的例子不可胜数,在传统的OO语言中(比如Java),代码的笼统更多的是运用接口(interface)来完成,而运用继续更多地是为了代码的复用(虽然如今强调运用组合而不是运用继续)。

怎样复用的?打个比如,class A 继续了 class B,class A便具有了class B 的public 和 protected范例的变量和要领,用最简朴的要领去想,就是 class B 将 这些属性和要领直接copy给class A,如许便完成了继续。

因而我们能够如许说,继续实际上是一品种与类之间的copy行动。

Javascript中的继续

在Javascript中没有类的观点,只要对象。虽然如今人们常常运用class关键字,这让Javascript看起来似乎是具有了”类”,可外表看到的不一定是实质,class只是一块糖,嚼碎了才晓得内里实在照样原型链那一套。因而,Javascript中的继续只是对象与对象之间的继续。反观继续的实质,继续就是让子类具有父类的一些属性和要领,那末在Javascript中就是让一个对象具有另一个对象的属性和要领。

所以,这给我了我们一条非常清楚的思绪,Javascript中怎样完成继续?只需让一个对象具有另一个对象的属性和要领,这就完成了。

应用Mixin

既然让一个对象具有另一个对象的属性和要领,起首想到的就是应用Mixin的粗犷体式格局,直接将对象的属性和要领强迫copy到另一个对象。

就像如许

function mixin(subObj, parentObj) {
for (var prop in parentObj) {
if (!(prop in subObj)) {
subObj[prop] = parentObj[prop]
}
}
}

固然也能够用ES6中的更文雅的Object.assign。

这段代码就完成了最简朴的从一个对象复制属性和要领到另一个对象。然则这类要领有一个缺点,假如父对象的属性是援用范例,比如一个对象或许数组,那末修正子对象的时刻必将会对父对象也形成修正,这明显不可接收。一种主意是采纳深度克隆,然则又可能会有轮回援用的题目。

所以,这类继续体式格局,比较合适对简朴对象的拓展,不太合适更庞杂的继续。

应用原型链

起首来讲一下什么是原型,原型在Javascript中,实在就是某个对象的一个属性。只不过这个属性很特别,关于外界平常是不可见(在chrome中能够经由过程__proto__猎取),我们平常把它叫作[[Prototype]]。这里和函数的prototype属性很相似但倒是两个东西,后面会提到。

那末什么是原型链呢,望文生义就像如许:

obj1.[[Prototype]] ===> obj2.[[Prototype]] ===> obj3.[[Prototype]]…. ===> Object.prototype

某一对象的原型属性中保存着另一个对象,以此类推,彷佛链子一样串起来。

链的尽头是Object.prototype对象,因而Object.prototype没有原型。当我们构建一个对象,这个对象的默许的原型就是Object.prototype

在chrome中考证一下:

var a = {}
Object.prototype === a.__proto__ // true

那末我们怎样用原型链完成继续呢?这要归功于Javascript中的托付机制。

当我们猎取一个对象的某个属性时,比如a.b,会默许挪用一个内置的[[Get]]要领,这个[[Get]]要领的算法就是:

在当前对象里查找,找不到则托付给当前对象的[[Prototype]],再找不到则托付给[[Prototype]]的[[Prototype]],直到Object.prototype中也没找到,则返回undefined。

因而,我们想让对象a具有对象b的属性和要领,即对象a继续对象b,只需要把b赋值给a的[[Prototype]],应用属性查找的托付机制,完成了a也”具有”了b的属性和要领,而且当a中有和b中的同名属性时,因为”屏障作用”,只要a中的属性会被优先猎取到,完成了override,看起来相称圆满。

new 和 “组织函数”

前面提到,[[Prototype]]是个内置隐蔽属性,虽然在chrome能够经由过程__proto__接见,然则其设想本意是不可被读取和修正的,那末我们怎样应用原型链来竖立继续关联?

Javascript供应了new关键字。

一般,在相似Java如许的OO语言中,new被用来实例化一个类,然则在Javascript中,new仅仅是一个函数挪用的体式格局!

Javascript中的函数也很新鲜,每个函数都有一个默许的prototype属性,这个差别于对象的[[Prototype]]属性,函数的prototype是有意暴露出来的,而且这个属性还不为空,另有prototype另有另一个属性叫constructor,这个constructor居然又援用回来了这个函数自身!因而我们看到的结果是如许的:

《Javascript的继续你相识若干?》

用new来挪用函数有什么差别的呢?new实在做了三件事:

  • 建立一个新对象
  • 将这个新对象的[[Prototype]]衔接到挪用函数的prototype上
  • 绑定挪用函数的this并挪用

用代码来示意就是:

function New(fn) {
var tmp = {}
tmp.__proto__ = fn.prototype
fn.call(tmp)
return tmp
}

能够看到,new帮我们把对象的[[Prototype]]衔接到了函数的prototype上。

到这儿,思绪就清楚了,怎样让对象a和对象b的[[Prototype]]相连完成a继续b?

只需把a的”组织函数”的[[Prototype]]衔接到b就好了。

来完成一下:

function A() {}
var b = {
show: function() {
console.log('这是来自b的要领')
}
}
A.prototype = b
// 这里修复了本来的 constructor
A.prototype.cOnstructor= A
var a = new A()
a.show() // 这是来自b的要领

更简朴的Object.create

ES5中供应的Object.create更简朴粗犷,能够直接建立一个对象并将这个对象的[[Prototype]]指向传入的对象

var b = {c: 1}
var a = Object.create(b)
console.log(a.c) // 1

模仿类继续

在Javascript中没有类的观点,虽然从ES6最先具有了class关键字,但其背地仍然是原型链作支持,所以这里照样用最实质的原型来模仿”类”的继续。这才是Javascript的本来面目!

/**
* 完成 A 继续 B
*/
function B(b) {
this.b = b
}
function A(a, b) {
// 挪用B并绑定this
B.call(this, b)
this.a = a
}
A.prototype = Object.assign({}, B.prototype)
A.prototype.cOnstructor= A
var c = new A(1, 2)
console.log(c.a) // 1
// c 具有了只要B的实例才具有的 b 属性
console.log(c.b) // 2

总结

简朴来讲,继续等于copy和复用,Javascript的继续实在就是应用原型链的查找和托付来完成属性和要领的复用,new关键字和”组织函数”只是衔接原型链的东西,如许的东西另有Object.create。


推荐阅读
  • 本文深入探讨了JavaScript中`this`关键字的多种使用方法和技巧。首先,分析了`this`作为全局变量时的行为;接着,讨论了其在对象方法调用中的表现;然后,介绍了`this`在构造函数中的作用;最后,详细解释了通过`apply`等方法改变`this`指向的机制。文章旨在帮助开发者更好地理解和应用`this`关键字,提高代码的灵活性和可维护性。 ... [详细]
  • C++ 开发实战:实用技巧与经验分享
    C++ 开发实战:实用技巧与经验分享 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • NOIP2000的单词接龙问题与常见的成语接龙游戏有异曲同工之妙。题目要求在给定的一组单词中,从指定的起始字母开始,构建最长的“单词链”。每个单词在链中最多可出现两次。本文将详细解析该题目的解法,并分享学习过程中的心得体会。 ... [详细]
  • 本文详细探讨了使用纯JavaScript开发经典贪吃蛇游戏的技术细节和实现方法。通过具体的代码示例,深入解析了游戏逻辑、动画效果及用户交互的实现过程,为开发者提供了宝贵的参考和实践经验。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • Codeforces 605C:Freelancer's Dreams —— 凸包算法解析与题解分析 ... [详细]
  • 在处理木偶评估函数时,我发现可以顺利传递本机对象(如字符串、列表和数字),但每当尝试将JSHandle或ElementHandle作为参数传递时,函数会拒绝接受这些对象。这可能是由于这些句柄对象的特殊性质导致的,建议在使用时进行适当的转换或封装,以确保函数能够正确处理。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • Squaretest:自动生成功能测试代码的高效插件
    本文将介绍一款名为Squaretest的高效插件,该工具能够自动生成功能测试代码。使用这款插件的主要原因是公司近期加强了代码质量的管控,对各项目进行了严格的单元测试评估。Squaretest不仅提高了测试代码的生成效率,还显著提升了代码的质量和可靠性。 ... [详细]
  • 在洛谷 P1344 的坏牛奶追踪问题中,第一问要求计算最小割,而第二问则需要找到割边数量最少的最小割。通过为每条边附加一个单位权值,可以在求解最小割时优先选择边数较少的方案,从而同时解决两个问题。这种策略不仅简化了问题的求解过程,还确保了结果的最优性。 ... [详细]
  • 如何精通编程语言:全面指南与实用技巧
    如何精通编程语言:全面指南与实用技巧 ... [详细]
author-avatar
xzcxzfvxvc
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有