资讯专栏INFORMATION COLUMN

__proto__ 和 prototype 会出现在什么地方?它们之间是什么关系?实现继承依赖什么?

bang590 / 3269人阅读

摘要:递归闭包原型继承本文主要讲解理清一些函数常用的知识点递归闭包是什么闭包使用场景什么是原型和原型链如何实现继承继承的原理,原文。当访问一个对象上的属性时,先尝试访问自身上的属性,再通过原型链尝试访问其构造函数原型上的属性。

递归、闭包、原型、继承

本文主要讲解、理清一些函数常用的知识点:递归、闭包是什么、闭包使用场景、什么是原型和原型链、如何实现继承、继承的原理,原文。

递归

函数的递归就是在函数中调用自身

举一个实例,著名斐波那契数列如何求得,问题是这样的:

第一个月初有一对刚诞生的兔子

第二个月之后(第三个月初)它们可以生育

每月每对可生育的兔子会诞生下一对新兔子

兔子永不死去

定义出来的数列是

我们需要求得 n 月有多少对兔子,通过递归算法可以求得

function fn(n) {
  return n < 2 ? 1 : fn(n - 1) + fn(n - 2)
}
var count = fn(30);
console.log(count);
闭包

什么是闭包?闭包就是函数,它可以继承并访问自身所被声明的函数作用域内的变量。

function fn1 () {
  var a = "hello"
  function fn2 () {
    console.log(a)
  }
}
fn1() // 其中 fn2 就是闭包函数
闭包的使用场景

闭包有很多使用场景,以下举例:

1. 私有变量
function Person(){    
  var name = "default";       
  return {    
    getName : function(){    
      return name;    
    },    
      setName : function(newName){    
      name = newName;    
    }    
  }    
};
var person = Person()
console.log(person.getName()) // default
person.setName("xiaomuchen")
console.log(person.getName()) // xiaomuchen
var person2 = Person()
console.log(person2.getName()) // default

上述函数,使用闭包创建私有变量 name,变量不可被外部直接操作、获取,只能通过返回的接口控制。

2. 匿名自执行函数

比如在开发页面时,需要在页面初始化时,你需要立即做一些操作,那么可以在页面中使用匿名自执行函数,它会在 JS 引擎读取到这部分代码时就立即执行。

// 在 title 上添加页面打开时间
(function(){
  var openTime = new Date()
  document.title = document.title + openTime
})();  
原型、原型链、继承

先问一个问题:__proto__ 和 prototype 会出现在什么地方?它们之间是什么关系?实现继承依赖什么?

__proto__ 和 prototype 的区别

1.JavaScript 中每一个对象都拥有原型链(__proto__)指向其构造函数的原型(prototype)

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

function Person () {}
Person.__proto__ === Function.prototype // true

var p = new Person()
p.__proto__ === Person.prototype // true

2.JavaScript 中每一个函数都拥有原型(prototype),原型也是一个对象,这个对象包括:原型链、原型方法(属性)、函数构造,同理它的原型链指向其构造函数的原型

function Person () {}
Person.prototype.getName = function () {}
Object.getOwnPropertyNames(Person.prototype) // ["constructor", "getName"]
Person.prototype.__proto__ === Object.prototype // true

3.当访问一个函数上的属性时,先尝试访问自身上的属性,再尝试访问其原型上的属性。当访问一个对象上的属性时,先尝试访问自身上的属性,再通过原型链尝试访问其构造函数原型上的属性。如果没有则通过原型上的原型链,继续向上查找,直到访问 Object.prototype 上的属性,如果还是没有,因为 Object.prototype 是一个没有 __proto__ 的对象,则查询到此为止,返回 undefined。

function Person () {}
Person.getName = function () {
  console.log("Person1")
}
Person.prototype.getName = function () {
  console.log("Person2")
}
var p = new Person()

Person.getName() // Person1
p.getName() // Person2
console.log(typeof p.getClass) // undefined
继承

JavaScript 函数通过原型和原型链实现继承

function superA (name) {
  this.name = name
}
superA.prototype.getName = function () {
  console.log(this.name)
}
function subA (name) {
  superA.call(this, name) // 继承属性
}
subA.prototype = new superA() // 继承方法

var a1 = new subA("xiaomuchen")
a1.getName() // xiaomuchen

上述代码,描述了一个函数的经典继承,其工作原理是这样的:

声明父类 superA、子类 subA

重写子类 subA 的原型,指向 superA 的实例

当实例化 a1 时,a1.__proto__ => subA.prototype => new superA() => superA.prototype,所以 a1 的构造函数是 superA

同时,运行 subA 也就是 superA.call(this, "xiaomuchen"),其中 this 指向 a1 所以 a1 继承了 name 属性

这样子类 subA 的实例 a1 就继承了 superA 的原型方法和属性

总结

本文概括了递归、闭包、原型、继承,理清这些基本的概念,有助于你接纳更多的东西,我们会在下一个章节对函数进行更深入的讨论。

作者:肖沐宸,github。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89523.html

相关文章

  • 我对JavaScript对象的理解

    摘要:通过这种操作,就有了构造函数的原型对象里的方法。你也看到了,就是一个普通对象,所以这种寄生式继承适合于根据已有对象创建一个加强版的对象,在主要考虑通过已有对象来继承而不是构造函数的情况下,这种方式的确很方便。 原文地址在我的博客, 转载请注明出处,谢谢! 标签: [es5对象、原型, 原型链, 继承] 注意(这篇文章特别长)这篇文章仅仅是我个人对于JavaScript对象的理解,并不是...

    roadtogeek 评论0 收藏0
  • JavaScript原型链以及Object,Function之间关系

    摘要:由于一般所有的原型链最终都会指向顶端的,所以它们都是的。好了现在了,成了所有对象原型链的。 JavaScript里任何东西都是对象,任何一个对象内部都有另一个对象叫__proto__,即原型,它可以包含任何东西让对象继承。当然__proto__本身也是一个对象,它自己也有自己的__proto__,这样一级一级向上,就构成了一个__proto__链,即原型链。当然原型链不会无限向上,它有...

    zacklee 评论0 收藏0
  • JS基础-原型、原型链真的不能一知半解

    摘要:原型链和对象的原型是对象实例和它的构造函数之间建立的链接,它的值是构造函数的。对象的原型根据上文提到的构造调用函数的时候会创建一个新对象,自动将的原型指向构造函数的对象。 showImg(https://segmentfault.com/img/remote/1460000020185197); JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清...

    changfeng1050 评论0 收藏0
  • 浅析JavaScript中原型及constructor、__proto__prototype的关系

    摘要:搞清了构造函数和原型的区别后,就可以继续了。指向构造函数的原型对象,存在于实例与构造函数的原型对象之间。要注意的是当我们使用下面这种将整个重写的情况时,会切断构造函数和原型之间的联系,也就是说不再指向了,而是指向。 前言 先说一说为什么要搞清楚JavaScript的原型,因为这就是JS的根。JavaScript虽然不是一门传统的面向对象语言,但它有自己的类和继承机制,最重要的就是它采用...

    wenzi 评论0 收藏0
  • 深入理解JavaScript

    摘要:深入之继承的多种方式和优缺点深入系列第十五篇,讲解各种继承方式和优缺点。对于解释型语言例如来说,通过词法分析语法分析语法树,就可以开始解释执行了。 JavaScript深入之继承的多种方式和优缺点 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎,再让我...

    myeveryheart 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<