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 ...
随机推荐
- Java properties | FileNotFoundException: properties (系统找不到指定的文件。)
文件存储路径的问题 错误描述 :FileNotFoundException: init.properties (系统找不到指定的文件.) 1.方法一 InputStream fis =TestProp ...
- Golang的安装和编译
一.下载安装(Ubuntu16.04) 1.下载地址:https://golang.google.cn/dl/ 2.下载Linux版本的安装包go1.10.3.linux-amd64.tar.gz并复 ...
- 媒体查询文字大小.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Swift3 Xcode8 Ios10 开发笔记
设置不同subView的层次: //将subView挪到最上边 self.view.bringSubviewToFront(subView) //将subView挪到最下边 self.view.sen ...
- Android应用程序权限说明
1.声明运行该应用本身所需要的权限 <!-- 声明该应用本身需要打电话的权限 --> <users-permission androd:name="android:perm ...
- Windows包管理器
Windows包管理器 Scoop 参考 安装命令 set-executionpolicy remotesigned -scope currentuser #用powershell执行 iex (ne ...
- 建议收藏:.net core 使用导入导出Excel详细案例,精心整理源码已更新至开源模板
还记得刚曾经因为导入导出不会做而发愁的自己吗?我见过自己前同事因为一个导出改了好几天,然后我们发现虽然有开源的库但是用起来却不得心应手,主要是因为百度使用方案的时候很多方案并不能解决问题. 尤其是尝试 ...
- (转载)学校搭建使用nginx同时编译rtmp-module进行直播的技术文档
原文地址:学校搭建使用 nginx 同时编译 rtmp-module 进行直播的技术文档 转载自我的大佬同学 MetalkgLZH.学校有几次需要全校观看网络直播的情况,但是学校的带宽不允许所有的班一 ...
- Java线程学习详解
线程基础 1. 线程的生命周期 1.1 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态.它保持这个状态直到程序 start() 这个线程. 1 ...
- Springboot中使用自定义参数注解获取 token 中用户数据
使用自定义参数注解获取 token 中User数据 使用背景 在springboot项目开发中需要从token中获取用户信息时通常的方式要经历几个步骤 拦截器中截获token TokenUtil工具类 ...