Giter Site home page Giter Site logo

JS原型链与继承相关 about drx HOT 6 OPEN

axlroseart avatar axlroseart commented on September 11, 2024
JS原型链与继承相关

from drx.

Comments (6)

axlroseart avatar axlroseart commented on September 11, 2024

简单回顾下构造函数,原型和实例的关系:

每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.

组合继承:

基本思路: 使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承.

const Father = function(name) {
 this.name = name
 this.height = 180
}
// 父类的原型方法
Father.prototype.sayName = function() {
 console.log(this.name)
}
// 子类
const Child = function(name) {
 Father.call(this, name)
}
Child.prototype = new Father()

Child的原型指向Father的构造函数:
image

// 子类实例1
const child1 = new Child('Gogo')
child1.sayName() // => Gogo
// 链式查找
child1
// 修改继承的属性
child1.height = 60

实例child1原型指向父类Father
image

// 子类实例2
const child2 = new Child('Coco')
child2.sayName() // => Coco
console.log(child2.height) // => 180

实例child1和实例child2都继承了Father的属性和方法且互不干扰,
但是这种实现方式使Father这个父类的构造函数被调用了两次。

Note:

使用构造函数可以避免原型上运用类型属性的共享;
call方法可以实现向父类传递参数;

原型继承

采用ES6的Object.create()方法

const person = {
 skinColor: ['black', 'white', 'yellow']
}
let gogo = Object.create(person)
gogo.skinColor.push('red')
let coco = Object.create(person)
coco.skinColor.push('blue')
console.log(person.skinColor) // => ["black", "white", "yellow", "red", "blue"]

image
可看出skinColor在gogo的原型属性上
Object.create的第二个参数与Object.defineProperties()方法的第二个参数格式相同:
每个属性都是通过自己的描述符定义的,以这种方式指定的任何属性都会覆盖原型对象上的同名属性。例如:

let aa = Object.create(person, { skinColor: { value: 'blackAndWhite' } })

image
提醒: 原型式继承中, 包含引用类型值的属性始终都会共享相应的值, 就像使用原型模式一样

new 的实现过程:

比如要实例化类F

const obj = {}
obj.__proto__ = F.prototype
F.call(obj)

属性查找

hasOwnProperty

判断属性是否为对象自身的属性,不会去原型上查找

instanceof 和 isPrototypeOf

isPrototypeOf 用来判断该方法所属的对象是否为参数的原型对象,比如:
console.log(Father.prototype.isPrototypeOf(child1))

instanceof 用来判断对象是否为构造器的一个实例

from drx.

axlroseart avatar axlroseart commented on September 11, 2024

this 根本不受原型的影响

无论在哪里找到方法:在对象或者原型中。调用方法时,this 始终是点之前的对象。

因此,实际上 setter 使用 admin 作为 this,而不是 user。

这是一件非常重要的事情,因为我们可能有一个有很多方法而且继承它的大对象。然后我们可以在继承的对象上运行它的方法,它们将修改这些对象的状态,而不是大对象的。

例如,这里的 animal 代表“方法存储”,而且 rabbit 在使用它。

调用 rabbit.sleep(),在 rabbit 对象上设置 this.isSleeping:

// animal has methods
let animal = {
  walk() {
    if (!this.isSleeping) {
      alert(`I walk`);
    }
  },
  sleep() {
    this.isSleeping = true;
  }
};

let rabbit = {
  name: "White Rabbit",
  __proto__: animal
};

// modifies rabbit.isSleeping
rabbit.sleep();

alert(rabbit.isSleeping); // true
alert(animal.isSleeping); // undefined (no such property in the prototype)

from drx.

axlroseart avatar axlroseart commented on September 11, 2024

每个函数都有 "prototype" 属性,即使我们不设置它。

默认的 "prototype" 是一个只有属性 constructor 的对象,它指向函数本身。

像这样:

function Rabbit() {}

/* default prototype
Rabbit.prototype = { constructor: Rabbit };
*/

from drx.

axlroseart avatar axlroseart commented on September 11, 2024

JavaScript 本身并不能确保正确的 "constructor" 函数值

是的,它存在于函数的默认 "prototype" 中,但仅此而已。之后会发生什么 —— 完全取决于我们自己。

特别是,如果我们将整个默认原型替换掉,那么其中就不会有构造函数。

例如:

function Rabbit() {}
Rabbit.prototype = {
  jumps: true
};

let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false

因此,为了确保正确的 "constructor",我们可以选择添加/删除属性到默认 "prototype" 而不是将其整个覆盖:

function Rabbit() {}
// Not overwrite Rabbit.prototype totally
// just add to it
Rabbit.prototype.jumps = true
// the default Rabbit.prototype.constructor is preserved

或者,也可以手动重新创建 constructor 属性:

Rabbit.prototype = {
  jumps: true,
  constructor: Rabbit
};

// 这样的 constructor 也是正确的,因为我们手动添加了它

from drx.

axlroseart avatar axlroseart commented on September 11, 2024
function Rabbit() {}
Rabbit.prototype = {
  eats: true
};

let rabbit = new Rabbit();

delete rabbit.eats;

alert( rabbit.eats ); // true

所有 delete 操作都直接应用于对象。这里 delete rabbit.eats 试图从 rabbit 中删除 eats 属性,但 rabbit 对象并没有 eats 属性。所以这个操作不会有任何 副作用。

from drx.

axlroseart avatar axlroseart commented on September 11, 2024

let user2 = new Object('Pete')
内置的 Object 构造函数忽略参数,它总是创建一个空对象 —— that's what we got from user2。

from drx.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.