我们都知道面向对象语言如 Java, C++ 等都基本实现了 封装, 继承, 多态 等特性, 用面向对象语言来编程的基本套路就是抽象出类, 然后实例化, 用实例调用方法来模拟进行程序间的通信.

但 JS 不是面向对象的语言, 或者我们称它的脚本语言, 它的一等公民就是 对象/函数. 本篇这里主要来说 JS 如何能进行模拟 OO 语言实现 继承 特性的, 即它巧妙的原型设计.

什么是 prototype

以前我也不懂这些东西, 后来用多了就渐渐懂了, 或者说先记住,会用等积累多了自然就明白了.

  • 任何函数都有 prototype 属性, 翻译成中文就是 "原型" 的意思, 它是一个指针, 指向原型对象
  • prototype 属性值是个 对象, 它默认拥有用 constructor 属性指向是函数自身
function sum(a, b) {
return a + b
} console.log('函数的原型是一个对象: ', sum.prototype, typeof sum.prototype)
console.log('次对象自有的 constructor 属性值是函数自身', sum.prototype.constructor); console.log(sum.prototype.constructor == sum);
console.log('1 + 1 的值是: ', sum.prototype.constructor(1, 1));
函数的原型是一个对象:  {} object
次对象自有的 constructor 属性值是函数自身 [Function: sum]
true
1 + 1 的值是: 2

这例子说明, 函数对象天生就有一个 prototype 属性, 它是一个对象. 且此对象的也天生具有一个 constructor 属性指向函数自身.

那这个感觉有点内循环的逻辑设计有什么用呢?

  • 普通函数的 prototype 属性确实没啥大作用, 但对于 构造函数 用大作用
  • 构造函数的 prototype 属性是它实例的原型

构造函数的 prototype 属性是它实例的原型

这个结论非常非常重要!!!

假设有一个构造函数:  People               // function
则它会自带一个原型属性: People.prototyep // object 现在它有一个实例: const youge = new People()
划重点!
youge.__ proto __ == People.prototype

这里的 __ proto __ 和 prototype 功能一样, 只是前者是浏览器添加的方法做兼容而已

只有函数对象才有 prototye, 其他对象不一定有. 但所有对象都有 __ proto __

function People(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
} // 实例化
var youge = new People('油哥', 18, '男') // 测试三角关系是否存在, 即实例的原型 是否等于 构造函数的 prototype
console.log(youge.__proto__ === People.prototype); // 返回 true

实例的原型, 是其构造函数的 prototype 属性, 这个结论真的是太重要啦!

可以想象成构造函数 People 是母亲, People.prototype 是父亲. 构造函数 (母亲) People 生出来的儿子 (实例) youge 的原型 __proto __ 就指向了他的父亲, 父亲的 constructor 类似配偶, 又指向了 People 母亲

这个说法似乎有点问题, 但意思差不多吧, 那这个东东到底有什么用呢 ?

答案就是: 原型链查找!

原型链查找

  • JS 规定, 实例可以打点访问它的原型上属性和方法, 这又被成为 原型链查找
function People(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
} // 在原型上添加属性和方法, 则实例都可以进行访问
People.prototype.want = '躺平' People.prototype.eat = function (name) {
return name
} // 实例化
var youge = new People('油哥', 18, '男') // 实例可访问它原型上的属性或方法
console.log('想: ', youge.want);
console.log('吃: ', youge.eat('肉肉')); console.log(youge) // 给对象绑定了同原型上同名方法时, 会遮蔽掉原型的
youge.want = '上班'
console.log('想: ', youge.want);
想:  躺平
吃: 肉肉 People { name: '油哥', age: 18, sex: '男' } 想: 上班

对象的 hasOwnProperty 方法

  • hasOwnProperty() 可以检查对象是否真正 自己拥有 某个属性或者方法
  • in 运算符只能检查某个属性或方法是否可以被对象访问, 不能检查 是否是自己
function People(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
} // 在原型上添加属性和方法, 则实例都可以进行访问
People.prototype.want = '躺平' People.prototype.eat = function (name) {
return name
} // 实例化
var youge = new People('油哥', 18, '男') console.log(youge.hasOwnProperty('name'));
console.log(youge.hasOwnProperty('sex'));
console.log(youge.hasOwnProperty('sex')); // 这个 want 是原型上的, 就不是自己的属性/方法啦
console.log(youge.hasOwnProperty('want')); // in 的话原型上的属性也会算给对象
console.log('want' in youge);
true
true
true
false
true

所以, 这个 in 还是没有像 Python 里面的 in 强大, 看来还是得用 hasOwnProperty() 稳一点.

可以看到这个原型还是真和面向对象里面的 类 有点像的, 但是我觉得它更巧妙一点呢. 同时, 如果我们要进行封装啥的, 那直接可以将方法和属性写到原型上, 这样就相等于面向对象中的 类方法, 让所有的实例对象都能使用, 同时更节约内存.

JS 原型链查找的更多相关文章

  1. js通过沿着作用域链还是原型链查找变量

    这是一道非常典型的JS闭包问题,结果和具体的解析请看这里. 对于其中的`函数作用域链的问题`博主似乎没有解释清楚,有一些疑问:js中的变量到底是沿着作用域链还是原型链查找呢? 首先,要分清作用域链与原 ...

  2. js原型链与继承(初体验)

    js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询 ...

  3. JS 原型链图形详解

    JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语 ...

  4. 谈谈我对 js原型链的理解

    想要学习 “原型链” 必须要认识什么是 “原型” 和 “原型链” 先理解一下普通的继承和原型的区别,下面写一段js代码来帮助理解: var Animal = function(){ // 动物抽象类 ...

  5. 简单粗暴地理解js原型链–js面向对象编程

    简单粗暴地理解js原型链–js面向对象编程 作者:茄果 链接:http://www.cnblogs.com/qieguo/archive/2016/05/03/5451626.html 原型链理解起来 ...

  6. JS原型链与继承别再被问倒了

    原文:详解JS原型链与继承 摘自JavaScript高级程序设计: 继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实 ...

  7. js原型链理解(2)--原型链继承

    1.原型链继承 2.constructor stealing(构造借用) 3.组合继承 js中的原型链继承,运用的js原型链中的__proto__. function Super(){ this.se ...

  8. JS原型链

    JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...

  9. 深入分析JS原型链以及为什么不能在原型链上使用对象

    在刚刚接触JS原型链的时候都会接触到一个熟悉的名词:prototype:如果你曾经深入过prototype,你会接触到另一个名词:__proto__(注意:两边各有两条下划线,不是一条).以下将会围绕 ...

  10. 深入理解JS原型链与继承

    我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天 ...

随机推荐

  1. 【ABP】项目示例(1)——项目搭建前置准备

    项目介绍 本项目使用.NET8+ABP+MySql搭建,基于DDD的设计思想,创建分层Web应用程序. 相关文档 .NET开发文档 Entity Framework Core开发文档 ABP开发文档 ...

  2. NFS服务器离线问题解决

    NFS服务器离线问题解决 NFS服务器挂了会导致挂载的NFS客户端主机卡顿延迟,或者提示找不到文件 因为在执行一些命令的时候会自动去同步,用作同步的NFS服务端挂了,命令执行就会卡住 不过听说NFS还 ...

  3. 嵌入式linux下的FTP服务器配置记录

    嵌入式linux FTP服务器 一般嵌入式Linux下的FTP服务器会有什么要求呢?一般来说差不多如下所示 账号认证,需要特定用户才能访问(不一定要和登录用户挂钩) 根目录固定在一个固定的位置,且不能 ...

  4. ssh远程连接linux服务器

    Linux,ssh远程连接 一. linux端配置 1.安装ssh服务 sudo apt-get update sudo apt-get install openssh-client sudo apt ...

  5. CART回归树基本原理(具体例子)

    id3不能直接处理连续性的特征,需要将连续性的转化成离散的,但是会破坏连续性特征的内在结构. 一.概念 CART全称叫Classification and Regression Tree.首先要强调的 ...

  6. 【由技及道】API契约的量子折叠术:Swagger Starter模块的十一维封装哲学【人工智障AI2077的开发日志】

    摘要:本文记录一个未来AI如何通过Swagger-Starter组件实现接口文档的维度折叠,让RESTful接口规范成为跨越时空的永恒契约. 动机:契约精神的量子困境 "一个软件?无外乎支持 ...

  7. HarmonyOS_Next 星河版迁移报错记录【自用】

    Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj- ...

  8. 第十八届全国大学生信息安全竞赛暨第二届“长城杯”铁人三项赛web方向部分wp

    第十八届全国大学生信息安全竞赛暨第二届"长城杯"铁人三项赛web方向部分wp hello_web 查看源代码发现有两个文件,访问一下 Tips是phpinfo 里面可以看到disa ...

  9. go切片排序

    前言 有时候我们需要根据切片中的某个字段进行切片排序,但sort包中只有默认基本类型 int . float64 和 string 的排序,所以我们可以手动实现sort包的 sort.Interfac ...

  10. AITCA联盟:渠道商的革命号角,产业变革的领航者!

    AITCA联盟:渠道商的革命号角,产业变革的领航者! 在AI技术风起云涌的今天,一场无声的革命正在悄然酝酿.在这场革命中,渠道商们不再是被动接受的附庸,而是即将成为改写产业规则.掌握自己命运的主宰者! ...