js基础之阮一峰的面向对象编程

 p是构造函数P的实例对象,

但是p自身没有constructor属性,该属性其实是读取原型链上面的P.prototype.constructor属性。

1
2
3
4
5
6
7
8
Animal.prototype.color = 'white'; //原型上写公共的方法或属性
 
//2 如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。
cat1.color = 'black';
 
cat1.color // 'black'
cat2.color // 'yellow'
Animal.prototype.color // 'yellow';

一  原型

1.复用:面对对象

面向对象编程是class来实现对象(类-接口)的继承,js则是通过“原型对象”.

1
2
3
4
5
6
7
8
9
public  class Person {
    int age;
    public Person(int a){
     age=a;
    }
    void speak(){
        System.out.println("今年我"+this.age+"岁");
    }
} 

很重要的一个方面,就是对象的继承,这对于代码的复用是非常有用的。

1
2
3
4
5
6
7
function Person(name){
   this.name=name;
   this.sum=function(){
       alert("this.name")
   }
 
}

  

2.构造函数的缺点:无法共享

JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板

构造函数继承的缺点:  

二个实例,拥有的方法也变成二个了,浪费系统资源。方法是共享的,应该也共享。

这个问题的解决方法,就是 JavaScript 的原型对象(prototype)。

js中继承机制的思想:是所有的方法和变量都可以共享。定义在原型上就可以共享。

js中函数的原型属性都指向一个对象。

1
2
3
4
5
6
7
8
9
10
function Dog(name, age) {
    this.name = name;
    this.age = age;
    <strong>this.log = function () {
        console.log(this.name + ":" + this.age);
    }</strong>
}
 
let dog1 = new Dog("小黄", 5);
let dog2=new Dog("小花",6);

 对普通的函数没有作用,对构造函数有作用。在外面用上prototype,原型属性和方法。原型对象的属性不是实例对象的属性。

二 原型链

所有对象都有自己的原型链,一个对象可充当的其他对象的原型; 原型对象也是对象,也有自己的原型。因此形成原型链“prototype Chain”

一层层追溯到最顶层就是Object.prototype,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOftoString方法的原因

Object.prototype的原型是null,没有任何属性和方法。

覆盖”:读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined

                如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding)。

缺点:一级级查找,找不到,会遍历整个原型链,那么很影响属性。 

1
2
typeof f.prototype     // "object"
Object.getPrototypeOf(Object.prototype) //null

 

三 constructor属性

prototype对象有一个constructor属性,默认执行原型对象所在的构造函数。因在原型上,那么构造可以被所有对象继承。 

1
2
3
4
function f(){}
var f=new f();
f.prototype.constructor===f
f.hasOwnProperty(constructor)

  

f 是 构造函数f 的 实例对象, f 本身没有construct。

修改原型的属性或方法时,同时也要修改constructor,不然导致这个属性不再指向Person。由于Person的新原型是一个普通对象,而普通对象的contructor属性指向Object构造函数,导致Person.prototype.constructor变成了Object

下面代码中,要么将constructor属性重新指向原来的构造函数,要么只在原型对象上添加方法,这样可以保证instanceof运算符不会失真。

 

1
2
3
4
5
6
7
8
C.prototype = {
  constructor: C,
  method1: function (...) { ... },
  // ...
};
 
// 更好的写法
C.prototype.method1 = function (...) { ... };

判断 类型

1
2
3
v instanceof Vehicle
// 等同于
Vehicle.prototype.isPrototypeOf(v)

  

四 面试题

 1.原型继承 

  B继承A,先有A与B,(就是先生成function A(){});

 缺点:新实例无法向父类构造函数传参

1
2
B.prototype=new A();
let newB=new B();

 2.call借用构造函数构成

在子元素的里面写上

1
fu.call(this,name),

 3.组合继承

引用自:https://javascript.ruanyifeng.com/oop/prototype.html#toc1

 

posted @   lxq3280  阅读(81)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结
点击右上角即可分享
微信分享提示