JS的原型和继承
__proto__
除null和undefined,JS中的所有数据类型都有这个属性; 它表示当我们访问一个对象的某个属性时,如果该对象自身不存在该属性, 就从它的__proto__属性上继续查找,以此类推,直到找到,若找到最后还是没有找到,则结果为undefined
我们把一个对象的__proto__属性所指向的对象叫该对象的原型;我们可以修改一个对象的原型来让这个对象拥有某种属性或某个方法
// 修改一个Number类型的值的原型
const num = 1;
num.__proto__.name = "My name is 1";
console.log(num.name); // My name is 1
// 修改一个对象的原型
const obj = {};
obj.__proto__.name = "dreamapple";
console.log(obj.name); // dreamapple
需注意的是,__proto__属性虽多数浏览器支持,但其实它仅在ECMAScript 2015规范中才被准确定义, 目的是为了给这个传统的功能定制一个标准,以确保浏览器间的兼容性。通过使用__proto__属性来修改一个对象的原型非常慢且影响性能。 所以,若想获取一个对象的原型,推荐用Object.getPrototypeOf 或Reflect.getPrototypeOf,设置一个对象的原型推荐用Object.setPrototypeOf或Reflect.setPrototypeOf
prototype
首先要记住的是,该属性一般只存在于函数对象上; 只要是能作为构造器的函数,都包含这个属性。即只要这个函数能通过new生成一个新对象, 那么这个函数肯定具有prototype属性。因为我们自定义的函数都可通过new生成一个对象,所以我们自定义的函数都有prototype 这个属性
// 函数字面量
console.log((function(){}).prototype); // {constructor: ƒ}
// Date构造器
console.log(Date.prototype); // {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
// Math.abs 不是构造器,不能通过new操作符生成一个新的对象,所以不含有prototype属性
console.log(Math.abs.prototype); // undefined
prototype属性有什么作用呢?作用就是:函数通过new生成的一个对象, 这个对象的原型(__proto__)指向该函数的prototype属性:
// 其中F表示一个自定义的函数或者是含有prototype属性的内置函数
new F().__proto__ === F.prototype // true
// 通过函数字面量定义的函数的__proto__属性都指向Function.prototype
(function(){}).__proto__ === Function.prototype // true
// 通过对象字面量定义的对象的__proto__属性都是指向Object.prototype
({}).__proto__ === Object.prototype // true
// Object函数的原型的__proto__属性指向null
Object.prototype.__proto__ === null // true
// 因为Function本身也是一个函数,所以Function函数的__proto__属性指向它自身的prototype
Function.__proto__ === Function.prototype // true
// 因为Function的prototype是一个对象,所以Function.prototype的__proto__属性指向Object.prototype
Function.prototype.__proto__ === Object.prototype // true
constructor
constructor表示一个对象的构造函数,除null和undefined,JS中的所有数据类型都有这个属性; 我们可通过下面的代码来验证一下:
null.constructor // Uncaught TypeError: Cannot read property 'constructor' of null ...
undefined.constructor // Uncaught TypeError: Cannot read property 'constructor' of undefined ...
(true).constructor // ƒ Boolean() { [native code] }
(1).constructor // ƒ Number() { [native code] }
"hello".constructor // ƒ String() { [native code] }
一个对象的constructor属性确切地说并不是存在这个对象上面的; 而是存在这个对象的原型上(如果是多级继承需手动修改原型的constructor属性),我们可用下面的代码来解释一下:
const F = function() {};
// 当我们定义一个函数的时候,这个函数的prototype属性上面的constructor属性指向自己本身
F.prototype.constructor === F; // true
对JS的原始类型(string, number, boolean, null, undefined, symbol (new in ECMAScript 2015)),它们的constructor属性是只读的,不可修改:
(1).constructor = "something";
console.log((1).constructor); // 输出 ƒ Number() { [native code] }
如果真想改这些原始类型的constructor属性,也不是不可以:
Number.prototype.constructor = "number constructor";
(1).constructor = 1;
console.log((1).constructor); // 输出 number constructor
当然上面的方式不推荐
原文链接:https://blog.csdn.net/u013747798/article/details/85988679
感谢给位的阅读,本人在休闲之余整理了一些资料和视频,并刚刚创建了一个交流群:907694362 欢迎进群一起讨论互相帮助,这 也是我之前刚开始学前端时候看的一些资料,希望对给位有所帮助,也祝各位在前端之路一帆风顺!!
JS的原型和继承的更多相关文章
- JS中原型链继承
当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...
- [js]js中原型的继承
js继承01 思路: 单例/工厂/构造函数--演进到原型 搞清原型结构 原型继承 模拟系统原型继承 实现自己的继承 观察原型继承特点 演进到原型链这一步 //单例模式: 防止变量名冲突: // 思路: ...
- 怎么理解js的原型链继承?
前言 了解java等面向对象语言的童鞋应该知道.面向对象的三大特性就是:封装,继承,多态. 今天,我们就来聊一聊继承.但是,注意,我们现在说的是js的继承. 在js的es6语法出来之前,我们想实现js ...
- js重点--原型链继承详解
上篇说过了关于原型链继承的问题,这篇详解一下. 1. function animals(){ this.type = "animals"; } animals.prototype. ...
- 关于JS的原型与继承笔记
1.什么是原型? 原型就是公用的方法或者属性. 1.prototype本质上还是一个JavaScript对象: 2.每个函数都有一个默认的属性prototype,而这个prototype的constr ...
- 破解 JS(原型)继承
总体分为四大类:利用空对象作为中介继承.Object.create 继承.setPrototypeOf 继承.拷贝继承 function Animal(name, age) { this.name = ...
- 8条规则图解JavaScript原型链继承原理
原形链是JS难点之一,而且很多书都喜欢用一大堆的文字解释给你听什么什么是原型链,就算有图配上讲解,有的图也是点到为止,很难让人不产生疑惑. 我们先来看一段程序,友情提示sublimeText看更爽: ...
- js中的原型、继承的一些想法
最近看到一个别人写的js类库,突然对js中的原型及继承产生了一些想法,之前也看过其中的一些内容,但是总不是很清晰,这几天利用空闲时间,对这块理解了一下,感觉还是有不通之处,思路上没那么条理,仅作为分享 ...
- js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。
js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } Class ...
随机推荐
- POI读入Excel用String读取数值类型失真问题(精度丢失)
问题:POI读取Excel数值单元格时,读取的小数数值与真实值不一致 话不多说,直接上代码! public static String getRealStringValue(Cell cell) { ...
- Spring Boot提供RESTful接口时的错误处理实践
使用Spring Boot开发微服务的过程中,我们会使用别人提供的接口,也会设计接口给别人使用,这时候微服务应用之间的协作就需要有一定的规范. 基于rpc协议,我们一般有两种思路:(1)提供服务的应用 ...
- 云计算 docker 容器使用命令
docker 使用命令: docker version 查看docker版本号 vi /etc/docker/daemon.json { "registry-mirrors": [ ...
- 如何在 GitHub 的项目中创建一个分支呢?
如何在 GitHub 的项目中创建一个分支呢? 其实很简单啦,直接点击 Branch,然后在弹出的文本框中添加自己的 Branch Name 然后点击蓝色的Create branch就可以了,这样一来 ...
- HashMap - 类注释
了解到Java8以后HashMap的实现换了,也看了很多博客一直在向我这个小菜鸡说HashMap的重要.因此我决定洗心革面,好好正视HashMap 基于jdk 8 先从类注释开始入手学习,顺便提高提高 ...
- javascript函数前面加~波浪线的作用
如下,在函数前加上波浪号,其作用是把函数声明转换为表达式,这样就可以直接运行. ~function sayHello(){ console.log('hello'); }() 测试: 在console ...
- 在ArangoDB中实现connectedcomponents算法
操作环境: tool:ArangoDB 3.3.13 操作系统:Debian 7.2.0-20 概念: Connected Components即连通体算法.用id标注图中每个连通体,将连通体中序号最 ...
- anaconda重装jupyter notebook后启动jupyter报错的问题
问题描述: 由于jupyter出现难以解决的问题,采用重新安装来解决问题,但是重装之后启动jupyter报错ImportError: libsodium.so.23: cannot open shar ...
- Swift3 Xcode8 Ios10 开发笔记
设置不同subView的层次: //将subView挪到最上边 self.view.bringSubviewToFront(subView) //将subView挪到最下边 self.view.sen ...
- Vue中Form表单验证无法消除验证问题
iView的表单api给出了一个resetFields方法,用于重置整个表单输入的内容并清除验证提示. 但是有时候需要只消除部分的iview的resetFields方法源码是这样的resetField ...