JavaScript高级之原型

显式原型与隐式原型

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<script type="text/javascript">
    function Fn() {// 构造函数创建对象,Fn本身是一个函数,也是一个对象

    }
    // 每一个函数都有一个prototype,即显式原型,属性
    console.log(Fn.prototype);

    var fn=new Fn();// 创建Fn的实例对象fn
    // 每一个实例对象都有一个__proto__,即隐式原型,属性
    console.log(fn.__proto__);

    // 实例对象的隐式原型的值为其对应构造函数的显式原型的值,即Fn.prototype===fn.__proto__返回true
    console.log(Fn.prototype===fn.__proto__);

    // 可以给原型添加方法,然后通过实例对象调用原型的方法
    Fn.prototype.hello=function () {
        console.log('hello world');
    };
    fn.hello();
</script>
</body>
</html>

在这里插入图片描述
总结:

  • 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象
  • 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
  • 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)。如Fn.prototype.hello就是操作显式原型。

在这里插入图片描述

原型

prototype

在JavaScript中,每个函数对象(函数是一种特别的对象)都有一个prototype属性,这个属性指向函数的原型对象。

<script type="text/javascript">
    function Fn() {

    }
    console.log(Fn);
</script>

在这里插入图片描述
在上述例子中,函数Fnprototype属性指向了一个对象,这个对象就是调用构造函数时创建的实例对象的原型对象。

原型:每一个JavaScript对象(除null外)创建的时候都会与另外一个对象相关联,这个对象就是我们所说的原型,每个对象都会从原型中“继承”属性。所谓的原型也是一个对象。
在这里插入图片描述

__proto__

每个实例对象(除null外)都有一个名为__proto__的属性,这个属性会指向该对象的原型。

<script type="text/javascript">
    function Person() {

    }

    console.log(Person);

    var person = new Person();// 创建实例对象
    console.log(person);

    console.log(Person.prototype === person.__proto__);// true
</script>

在这里插入图片描述

constructor

每个原型对象都有一个constructor属性,指向该关联的构造函数。

<script type="text/javascript">
    function Person() {

    }

    console.log(Person);// 构造函数对象

    var person = new Person();// 创建实例对象
    console.log(person);

    console.log(Person === Person.prototype.constructor);// true
    console.log(Person === person.__proto__.constructor);// true
</script>

在这里插入图片描述特别说明:

<script type="text/javascript">
    function Person() {

    }

    console.log(Person);// 构造函数对象

    var person = new Person();// 创建实例对象
    console.log(person);

    console.log(person.constructor === Person);// true
</script>

当获取 person.constructor 时,其实 person 中并没有 constructor 属性,不能读取到constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以:person.constructor === Person.prototype.constructor

原型链

查找实例属性

当读取实例对象的属性时,如果找不到则会查找与对象相关联的原型对象中的属性,如果还查找不到,则会去找原型的原型,一直会查找到最顶层为止。

<script type="text/javascript">
    function Person() {

    }

    Person.prototype.name = '张三';
    console.log(Person);// 构造函数对象

    var person = new Person();// 创建实例对象
    person.name = 'Tom';
    console.log(person);
    console.log(person.name);

    delete person.name;// 删除name属性

    console.log(person);
    console.log(person.name);
</script>

我们给实例对象person添加了name属性,当我们打印person.name时打印的结果是Tom。当我们执行delete person.name删除name属性时,再读取person.name时从person对象中找不到name属性,就会从person的原型对象即person.__proto__(即Person.prototype)中查找,找到了name属性的结果为张三
在这里插入图片描述

原型链

原型也是一个对象,如Person.prototypeperson.__proto__指向的原型对象。在这里插入图片描述既然是对象,那么也有__proto__属性,它的值也是一个原型对象,那么Person.prototype.__proto__person.__proto__.__proto__就是原型的原型。等于Object.prototype(即Person.prototype.__proto__===Object.prototype)。
在这里插入图片描述Object.prototype.__proto__为null,即Object的原型对象是原型链尽头。
在这里插入图片描述注意:一般情况下方法定义在原型中,而属性一般通过构造函数定义在对象本身上。如:

<script type="text/javascript">
// 1. 读取对象的属性值时: 会自动到原型链中查找
// 2. 设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值
  function Fn() {

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

  var fn2 = new Fn()
  fn2.a = 'yyy'
  console.log(fn1.a, fn2.a, fn2)

  function Person(name, age) {
    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)

  var p2 = new Person('Jack', 12)
  p2.setName('Cat')
  console.log(p2)
  console.log(p1.__proto__===p2.__proto__) // true
</script>

instanceof是如何判断的

A instanceof B判断原理:如果B函数的显式原型对象在A对象的原型链上, 返回true, 否则返回false。

<script type="text/javascript">
  function Foo() {  }
  var f1 = new Foo()
  console.log(f1 instanceof Foo) // true
  console.log(f1 instanceof Object) // true
</script>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值