原型与继承与class

对象有属性(专业点叫静态属性)和方法(专业点叫静态方法)和原型属性和原型方法

除了系统自带的那么几百万个对象,我们自己写在js的创建的对象,自定义的对象,都来自对象的构造函数,用来构造对象的函数,叫做构造函数,es6的class也是构造函数,就是一个语法糖而已,还是个残缺的语法糖

// 写一个完整的构造函数
// 构造函数的name一般首字母大写,为了好认
function User(name){
   // 静态属性
   this.name = name;
   // 静态方法
   this.say = function(){ ... }
}
// 原型对象
User.prototype = {
   //原型属性
   prototypeName: "proName",
   //原型方法
   prototypeSay: function(){ ... }
}
// 构造函数的私有属性
User.aa = "aa"
// 构造函数的私有方法
User.bb= function(){ ... }
class User{
  constructor(name) {
    //原型属性
    this.name = name;
    //原型方法
    this.say = function(){ ... }
  }
  //原型方法,没有原型属性
  prototypeSay(){ ... },
  // 构造函数的私有属性
  static aa = "aa"
  // 构造函数的私有方法
  static bb = function(){ ... }
}

构造函数是为了能够大批量的生产方法属性一样,只有某几个通过传参不同而构造属性不同的对象而诞生的工厂,并且可以通过继承使方法被无限传递或者重写才是构造函数的精髓

原生的继承方式有六种

但最前面的五个各有缺陷,直接上完美方式的代码,寄生组合继承
其他几种自己搜,不混淆

// 父函数SuperType
function SuperType(country) {
  this.country = country;
  this.sayCountry = function() {
     console.log(this.country);
  }
}
// 父函数SuperType的原型方法
SuperType.prototype.proSay = function() {
  console.log(this.country);
}
// 子函数SuperType
function SubType(country,age) {
  SuperType.call(this,country);
  this.age = age;
}
// 核心代码,继承
function inheritPrototype(subType,SuperType) {
  var prototype = Object(SuperType); // 创建对象
  prototype.constructor = subType; // 增强对象
  subType.prototype = prototype; // 指定对象
}
// 继承方法执行,参数是(子,父)
inheritPrototype(SubType,SuperType); 

// 继承完成后
// 子函数添加原型对象
SubType.prototype.sayAge = function() {
  console.log(this.age);
}
var a = new SuperType("中国")
var b = new SubType("中华",18)

class语法糖

class SuperType{
  constructor(country) {
    this.country = country;
    this.sayCountry = function(){}
  }
  proSay(){  },
}

class SubType extend SuperType{
  constructor(age) {
    super();
    this.age = age;
  }
  sayAge(){  },
}
var a = new SuperType("中国")
var b = new SubType("中华",18)

==继承的成功就是在于,子函数有父函数的方法,父函数没有子函数的新方法==
上面两个写法打印出来如下图,都符合继承的要求

原型链的走向
先上个图,图上没有关于继承的答案,这个图能看一年

分析过程就不说了,需要自己理解,说说几个理论
一个对象的__proto__属性等于对象的构造函数的prototype对象
上面说的这个属性/对象,他的constructor属性又指向构造函数本事
所有function的__proto__都指向Function的prototype,包括Function自己,这是个环

一个面试题
问:
C构造函数继承于构造函数B,B构造函数继承于构造函数A,问C的原型链怎么走到null
答案:
继承者的prototype的prototype的prototype...直到prototype为underfind时说明到了function原型的终点,也就是到了Object层,这时取出__proto__(这个__proto__也就是Object的prototype),再取一层__proto__就是null(尽头)

先有鸡先有蛋
这是个新有函数还是先有对象的问题,函数是对象,对象通过函数new出来,这是个相互嵌套的关系,但是程序肯定是有一个终点的,那到底是先有鸡还是先有蛋

我找到了两个答案
答案一
先有的Object.prototype, Object.prototype构造出Function.prototype,然后Function.prototype构造出Object和Function。
Object.prototype是鸡,Object和Function都是蛋。

答案二
函数function就是对象,所有的函数是被Function这个函数对象构造出来的。Function是最顶层的构造器。它构造了系统中所有的对象,包括用户自定义对象,系统内置对象,甚至包括它自已。这也表明Function具有自举性(自已构造自己的能力)。这也间接决定了Function的call和constructor逻辑相同。每个对象都有一个 constructor 属性,用于指向创建其的函数对象。

我更相信第二个答案

new的原理,模拟一个new

function new(func) {
   let target = new Object();
   target.__proto__ = func.prototype;
   let res = func.call(target);
   if (res && typeof(res) == "object" || typeof(res) == "function") {
    return res;
   }
   return target;
}

原文地址:https://www.cnblogs.com/pengdt/p/12037973.html

时间: 2024-10-12 13:30:29

原型与继承与class的相关文章

JavaScript 随笔2 面向对象 原型链 继承

第六章 面向对象的程序设计 1.创建对象的几种方式 A)工厂模式 function CreatObj(name,sex,age){ this.name=name; this.sex=sex; this.age=age; } 缺点:虽然可以批量创建对象,却不能知道对象的类型 只知道他是Object类型: B)构造函数 function Person(name,sex){ this.name=name; this.sex=sex; this.sayName=function(){ alert(thi

JavaScript之基础-16 JavaScript 原型与继承

一.JavaScript 原型 原型的概念 - 在JavaScript中,函数本身也是一个包含了方法和属性的对象 - 每个函数中都有一个prototype属性,该属性引用的就是原型对象 - 原型对象是保存共享属性值和共享方法的对象 为对象扩展属性 - 扩展单个对象的成员 - 扩展共享的属性值 - 内存图描述 删除属性 - 可以使用delete关键字删除对象的属性 自由属性与原型属性 - 自有属性:通过对象的引用添加的属性;其它对象可能无此属性;即使有,也是彼此独立的属性 emp1.job = '

javascript原型链继承

一.关于javascript原型的基本概念: prototype属性:每个函数都一个prototype属性,这个属性指向函数的原型对象.原型对象主要用于共享实例中所包含的的属性和方法. constructor属性:每个原型对象都有一个constructor属性,这个constructor属性包含一个指向prototype属性所在函数的指针. 例如 Foo.prototype.constructor指向Foo函数.这个属性是只读的. __proto__属性(ES6通过对__proto__属性进行标

面向对象的原型与继承

1. 为什么需要原型 构造器创建对象的时候, 实际上会有成员重复 如果使用 构造器 this.方法名 = function .... 方式创建对象. 那么每一个对象 对应的方法就会重复. 解决办法就是让这个方法( 函数 )共享 -> 将函数写到外面, 那么 Person 在初始化对象的时候就不会再创建一个函数了. 只需要将 外面的函数引用 交给对象即可. 缺点: 一个对象可能有 n 多方法. 如果将所有的东西 都放到外面, 与其他库 冲突的几率就会变大. 所以不宜采取该方法. -> 将所有的方

js中的原型、继承的一些想法

最近看到一个别人写的js类库,突然对js中的原型及继承产生了一些想法,之前也看过其中的一些内容,但是总不是很清晰,这几天利用空闲时间,对这块理解了一下,感觉还是有不通之处,思路上没那么条理,仅作为分享, 一.instanceof 在JavaScript有instanceof运算符,是二元运算符,使用方法 instanceA instanceof A,返回值是布尔值(boolean),含义是判断instanceA是否是A的一个实例,其实质是判断A.prototype===instanceA.__p

JS面向对象,原型,继承

ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同.var box = new Object();box.name = 'Lee';box.age = 100;box.run = function(){ return this.name + this.age + '运行中...'; //th

面向对象之笔记二——————原型与继承

原型与继承 原型 为什么需要原型? 构造器创建对象的时候, 实际上会有成员重复 如果使用 构造器 this.方法名 = function .... 方式创建对象. 那么每一个对象对应的方法就会重复 function Person( name ) { this.name = name; this.sayHello = function() { console.log( '你好,我是 ' + this.name ); }; } var p1 = new Person( 'Hello' ); var

《javascript高级程序设计(第二版)》学习(4)原型与继承

声明:这类属于学习笔记,主要是摘录书中内容,比较少的整理.内容经常是跳跃的,建议您阅读书本,收益更大. function Person(){} Person.prototype.name="tom"; //这里等于重写了原型对象 //切断了与构造函数之间的联系 Person.prototype={ name:"mike", age:22 }; //得到的不是Person了,而是Object console.log(Person.prototype.construct

原型与继承学习笔记4

经过前三节的研究,我们终于可以对js这门无法实现接口继承的语言进行实现继承,为了更好的面向对象..... 原型链继承 这个原型链我们上节引用了一下,用它实现继承的基本思想是利用原型让一个引用类型引用另一个引用类型的属性和方法.即把一个函数(狭义上来举例)的所有属性和方法(这个函数的实例)赋值给另一个函数的prototype,使一个函数的实例可以通过__proto__原型一层层的调用另一个函数的所有属性. 有点绕,简单的说就是把超类的实例赋值给子类的prototype.看个例子: 1 functi

JavaScript中的原型和继承

请在此暂时忘记之前学到的面向对象的一切知识.这里只需要考虑赛车的情况.是的,就是赛车. 最近我正在观看 24 Hours of Le Mans ,这是法国流行的一项赛事.最快的车被称为 Le Mans 原型车.这些车虽然是由"奥迪"或"标致"这些厂商制造的,可它们并不是你在街上或速公路上所见到的那类汽车.它们是专为参加高速耐力赛事而制造出来的. 厂家投入巨额资金,用于研发.设计.制造这些原型车,而工程师们总是努力尝试将这项工程做到极致.他们在合金.生物燃料.制动技术