JS的原型和继承

参考文献

JavaScript原型与继承的秘密

__proto__

nullundefined,JS中的所有数据类型都有这个属性; 它表示当我们访问一个对象的某个属性时,如果该对象自身不存在该属性, 就从它的__proto__属性上继续查找,以此类推,直到找到,若找到最后还是没有找到,则结果为undefined

我们把一个对象的__proto__属性所指向的对象叫该对象的原型;我们可以修改一个对象的原型来让这个对象拥有某种属性或某个方法

 


 
 
  1. // 修改一个Number类型的值的原型
  2. const num = 1;
  3. num.__proto__.name = "My name is 1";
  4. console.log(num.name); // My name is 1
  5. // 修改一个对象的原型
  6. const obj = {};
  7. obj.__proto__.name = "dreamapple";
  8. console.log(obj.name); // dreamapple

需注意的是,__proto__属性虽多数浏览器支持,但其实它仅在ECMAScript 2015规范中才被准确定义, 目的是为了给这个传统的功能定制一个标准,以确保浏览器间的兼容性。通过使用__proto__属性来修改一个对象的原型非常慢且影响性能。 所以,若想获取一个对象的原型,推荐用Object.getPrototypeOf 或Reflect.getPrototypeOf,设置一个对象的原型推荐用Object.setPrototypeOfReflect.setPrototypeOf

prototype

首先要记住的是,该属性一般只存在于函数对象上; 只要是能作为构造器的函数,都包含这个属性。即只要这个函数能通过new生成一个新对象, 那么这个函数肯定具有prototype属性。因为我们自定义的函数都可通过new生成一个对象,所以我们自定义的函数都有prototype 这个属性


 
 
  1. // 函数字面量
  2. console.log(( function(){}).prototype); // {constructor: ƒ}
  3. // Date构造器
  4. console.log( Date.prototype); // {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
  5. // Math.abs 不是构造器,不能通过new操作符生成一个新的对象,所以不含有prototype属性
  6. console.log( Math.abs.prototype); // undefined

prototype属性有什么作用呢?作用就是:函数通过new生成的一个对象, 这个对象的原型(__proto__)指向该函数的prototype属性


 
 
  1. // 其中F表示一个自定义的函数或者是含有prototype属性的内置函数
  2. new F().__proto__ === F.prototype // true
  3. // 通过函数字面量定义的函数的__proto__属性都指向Function.prototype
  4. ( function(){}).__proto__ === Function.prototype // true
  5. // 通过对象字面量定义的对象的__proto__属性都是指向Object.prototype
  6. ({}).__proto__ === Object.prototype // true
  7. // Object函数的原型的__proto__属性指向null
  8. Object.prototype.__proto__ === null // true
  9. // 因为Function本身也是一个函数,所以Function函数的__proto__属性指向它自身的prototype
  10. Function.__proto__ === Function.prototype // true
  11. // 因为Function的prototype是一个对象,所以Function.prototype的__proto__属性指向Object.prototype
  12. Function.prototype.__proto__ === Object.prototype // true

constructor

constructor表示一个对象的构造函数,除nullundefined,JS中的所有数据类型都有这个属性; 我们可通过下面的代码来验证一下:


 
 
  1. null. constructor // Uncaught TypeError: Cannot read property 'constructor' of null ...
  2. undefined. constructor // Uncaught TypeError: Cannot read property 'constructor' of undefined ...
  3. ( true). constructor // ƒ Boolean() { [native code] }
  4. ( 1). constructor // ƒ Number() { [native code] }
  5. "hello". constructor // ƒ String() { [native code] }

一个对象的constructor属性确切地说并不是存在这个对象上面的; 而是存在这个对象的原型上(如果是多级继承需手动修改原型的constructor属性),我们可用下面的代码来解释一下:


 
 
  1. const F = function() {};
  2. // 当我们定义一个函数的时候,这个函数的prototype属性上面的constructor属性指向自己本身
  3. F.prototype. constructor === F; // true

对JS的原始类型(stringnumberbooleannullundefinedsymbol (new in ECMAScript 2015)),它们的constructor属性是只读的,不可修改:


 
 
  1. ( 1). constructor = "something";
  2. console.log(( 1). constructor); // 输出 ƒ Number() { [native code] }

如果真想改这些原始类型的constructor属性,也不是不可以:


 
 
  1. Number.prototype. constructor = "number constructor";
  2. ( 1). constructor = 1;
  3. console.log(( 1). constructor); // 输出 number constructor

当然上面的方式不推荐

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值