0
点赞
收藏
分享

微信扫一扫

JS 原型与原型链


先熟悉概念,对于JS原型与原型链 有个大致了解:

原型:
JS是一种通过原型实现继承的语言与别的高级语言是有区别的,像JAVA,C#是通过类型决定继承关系的,JS是动态的弱类型语言,总之,可以认为JS中所有都是对象,在JS中,原型也是一个对象,通过原型可以实现对象的属性继承,JS的对象中都包含了一个prototype内部属性,这个属性所对应的就是该对象的原型。prototype作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,Firefox和Chrome内核的JS引擎中提供了proto这个非标准的访问器(ECMA新标准中引入了标准对象原型访问器Object.getPrototype(object))。原型的主要作用就是为了实现继承与访问对象。

原型链:
当我们去访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是说我们平时所说的原型链的概念。

一、原型

  1. 函数的prototype属性
  • 每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为:原型对象)
  • 原型对象中有一个属性constructor,它指向函数对象。
  • JS 原型与原型链_原型

  1. 给原型对象添加属性(一般都是方法)
    作用:函数的所有实例对象都自动拥有原型中的属性(方法)。
  2. 代码示例:

// 每个函数都有一个prototype属性,它默认指向一个Object空对象。(也就是原型对象)
console.log(Date.prototype, typeof Date.prototype);

function Fun() {}
console.log(Fun.prototype); // 默认指向一个Object空对象(没有我们的属性)

// 原型对象中有一个属性construtor,它指向函数对象
console.log(Date.prototype.constructor === Date);
console.log(Fun.prototype.constructor === Fun);

// 给原型对象添加属性(一般是方法) ===> 实例对象可以访问
Fun.prototype.ok = function() {
console.log('ok');
}
var fun = new Fun()
fun.ok()

二、显式原型与隐式原型

  1. 每个函数function都有一个prototype,即显式原型(属性)
  2. 每个实例对象都有一个__proto__,可称为隐式原型(属性)
  3. 对象的隐式原型为其对应构造函数的显式原型的值
  4. 内存结构:
  5. JS 原型与原型链_前端_02

  6. 总结:
  • 函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object对象。
  • 对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性值
  • 程序员可以直接操作显示原型,但不能操作隐式原型(ES6之前)
  1. 代码示例:

//定义构造函数
function Fn() {
// 内部默认执行语句: this.prototype = {}
}
// 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象
console.log(Fn.prototype)
// 2. 每个实例对象都有一个__proto__,可称为隐式原型
//创建实例对象
var fn = new Fn() // 内部默认执行语句: this.__proto__ = Fn.prototype
console.log(fn.__proto__)
// 3. 对象的隐式原型的值为其对应构造函数的显式原型的值
console.log(Fn.prototype===fn.__proto__) // true
//给原型添加方法
Fn.prototype.test = function () {
console.log('test()')
}
//通过实例调用原型的方法
fn.test()

三、原型链

①原型链

  1. 原型链
  • 访问对象的一个属性时,
  • 先在自身属性中查找,找到返回
  • 如果没有,再沿着__proto__这条链向上查找,找到返回。
  • 如果最终没找到,返回undefined。

function Fn() {
this.test1 = function() {
console.log('test1()');
}
}
Fn.prototype.test2 = function() {
console.log('test2()');
}
var fn = new Fn()
fn.test1()
fn.test2()
console.log(fn.toString());
fn.test3()

JS 原型与原型链_前端_03

  • 别名:隐式原型链
  • 作用:查找对象的属性(方法)

②构造函数、原型、实例对象的关系(图解)

  1. var o1 = new Object();
    var o2 = {};

JS 原型与原型链_前端_04

  1. function Foo(){ }
  2. JS 原型与原型链_原理_05

  3. ps: 因为所有函数是Function函数对象的实例对象,所以所有的函数的[proto](隐式原型属性) 都是一样的,都指向 Function 的原型对象。

③ 属性问题

  • 读取对象的属性值时:会自动到原型链中查找
  • 设置对象的属性值时:不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值。
  • 方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
  • 代码示例:

function Fn() { }
Fn.prototype.a = 'xxx'
var fn1 = new Fn()
console.log(fn1.a, fn1) //xxx Fn{}

var fn2 = new Fn()
fn2.a = 'yyy'
console.log(fn1.a, fn2.a, fn2) //xxx yyy Fn{a: "yyy"}

function Person(name,) {
this.name = name
this.age = age
}
Person.prototype.setName = function (name) {
this.name = name
}
var p1 = new Person('Tom', 12)
p1.setName('Bob')
console.log(p1) //Person {name: "Bob", age: 12}

var p2 = new Person('Jack', 12)
p2.setName('Cat')
console.log(p2) //Person {name: "Cat", age: 12}
console.log(p1.__proto__===p2.__proto__) // true -->所以方法一般定义在原型中

四、instanceof

  1. instanceof 是如何判断的?
  • 表达式:A instanceof B
  • 如果B函数的显式原型对象在A对象的原型链上,返回true,否则返回false
  1. Function是通过new 自己产生的实例

/*
案例1
*/
function Foo() { }
var f1 = new Foo()
console.log(f1 instanceof Foo) // true
console.log(f1 instanceof Object) // true

/*
案例2
*/
console.log(Object instanceof Function) // true
console.log(Object instanceof Object) // true
console.log(Function instanceof Function) // true
console.log(Function instanceof Object) // true

function Foo() {}
console.log(Object instanceof Foo) // false

五、相关面试题

测试题1:

/*
测试题1
*/
function A () {}
A.prototype.n = 1
let b = new A()
A.prototype = { n: 2, m: 3}
let c = new A()
console.log(b.n, b.m, c.n, c.m) // 1 undefined 2 3

测试题2:

/*
测试题2
*/
function F (){}
Object.prototype.a = function(){
console.log('a()')
}
Function.prototype.b = function(){
console.log('b()')
}

let f = new F()
f.a() //a()
f.b() //f.b is not a function -->找不到
F.a() //a()
F.b() //b()

console.log(f)
console.log(Object.prototype)
console.log(Function.prototype)


举报

相关推荐

0 条评论