亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

javascript-原型、原型鏈深入理解

標簽:
JavaScript

通过阅读本文你会了解到什么是:原型和原型链、普通对象和函数对象、__proto__prototype、构造函数(constructor)

1、普通对象和函数对象

在javascript中万物皆对象,对象分为普通对象和函数对象,可以通过typeof来判断对象是哪一种类型的对象。

1.1 普通对象

typeof obj === 'object'; // true

let obj1 = {};let obj2 = new Object();let obj3 = new Array();console.log(typeof obj1); // objectconsole.log(typeof obj2); // objectconsole.log(typeof obj3); // object

1.2 函数对象

typeof obj === 'function'; // true

let f1 = new Function('a', 'b', 'return a + b');let f2 = function () {};function f3() {};console.log(typeof f1); // functionconsole.log(typeof f2); // functionconsole.log(typeof f3); // functionconsole.log(typeof Function); // functionconsole.log(typeof Object); // functionconsole.log(typeof Array); // functionconsole.log(Function.constructor === Function); // trueconsole.log(Object.constructor === Function); // trueconsole.log(Array.constructor === Function); // true

注: 凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。f1,f2,f3,实际上也是要通过 new Function()的方式进行创建。Function Object 也是通过 New Function()创建的。javascript大部分内置构造器属于函数对象

2、构造函数

构造函数是用来初始化新创建的对象的,属于函数对象。

(1)使用构造函数创建两个实例

function Student(name, age) {    this.name = name;    this.age = age;
}let student1 = new Student('Ada', 23);let student2 = new Student('Bob', 25);console.log(student1.name, student1.age); // Ada 23console.log(student2.name, student2.age); // Bob 25console.log(typeof Student); // function

如果使用构造函数来初始化新创建的对象,记得用new关键字。

(2)错误示范:如果不用new关键字,那么this就会指向当前调用该构造函数的对象,本例中是window

let student3 = Student('Sunny', 23);console.log(student3); // undefinedconsole.log(window.name, window.age); // Sunny 23

(3)构造函数创建的实例和构造函数间的关系

console.log(student1.constructor === Student); // trueconsole.log(student2.constructor === Student); // true

注: 用构造函数创建的实例都具有constructor属性,该属性指向其构造函数。实例.constructor === 构造函数

3、原型(原型对象)- prototype

  • 原型是一个对象(也被称为原型对象),是类的核心,可以通过原型实现原型(对象)的属性继承。

  • 某些对象有些预定义的属性,其中函数对象有一个prototype对象,指向其原型对象

(1)创建两个Student实例

function Student(name, age) {    this.name = name;    this.age = age;
}
Student.prototype.sayHello = function () {    console.log(`hello ${this.School}, my name is ${this.name}.`);
};
Student.prototype.School = 'CUIT';let student1 = new Student('Ada', 23);let student2 = new Student('Bob', 25);
student1.sayHello(); // hello CUIT, my name is Ada.student2.sayHello(); // hello CUIT, my name is Bob.console.log(student1.prototype); // undefined

通过对构造函数的原型对象的属性赋值,可以让所有的实例都具有构造函数.prototype中的所有属性。其属性值中的this指代当前实例对象(最好不要用箭头函数来书写函数,不然this的指代不同)。
所以: prototype属性只有函数对象才有。

(2)Student.prototype


webp

Student.prototype

console.log(Student.prototype.constructor === Student); // true

原型对象具有constructor属性,指向prototype属性所在的函数(构造函数)。上文我们有推断实例.constructor === 构造函数,所以我们可以仅仅认为(Student.prototype instanceof Student ; // false构造函数.prototype是构造函数的一个实例。

(3)特殊的Function.prototype

一般情况下我们可以认为原型对象是一个普通对象,但是Function.prototype是一个函数对象。我们上文提到过凡是通过 new Function() 创建的对象都是函数对象,且我们可以认为构造函数.prototype是构造函数的一个实例,所以Function.prototype就是一个函数对象

webp

Function.prototype


4、_proto_

javascript在创建对象时候,都有一个叫做__proto__的内置属性,用于指向创建它的构造函数的原型对象。但是__proto__并不是一个规范的属性,只有部分浏览器(比如:Firefox和Chrome)才支持。

console.log(student1.__proto__ === Student.prototype); // true

实例.__proto__ === 构造函数t.prototype; // true

webp

《JavaScript 高级程序设计》的图 6-1


(1)实例的_proto_和构造函数及其原型间的关系


function testProto(factory) {    let obj = new factory();    console.log(obj.constructor === factory);    console.log(obj.__proto__ === factory.prototype);
}

testProto(Array); // true truetestProto(Date); // true truetestProto(Function); // true true

(2)javascrpt部分内置构造器和Function间的关系

console.log(Date.constructor === Function); // trueconsole.log(Date instanceof Function); // trueconsole.log(Date.__proto__ === Function.prototype); // trueconsole.log(Object.constructor === Function); // trueconsole.log(Object instanceof Function); // trueconsole.log(Object.__proto__ === Function.prototype); // trueconsole.log(Function.constructor === Function); // trueconsole.log(Function instanceof Function); // trueconsole.log(Function.__proto__ === Function.prototype); // true

所有函数对象的proto都指向Function.prototype,它是一个空函数(Empty function),但是其原型对象有一些内置的属性:如length、call、apply、bind等

(3)Function.prototype.__proto__

console.log(Function.prototype.__proto__ === Object.prototype); // true

这说明所有的构造器也都是一个普通对象,所以可以给构造器添加/删除属性等。同时它也继承了Object.prototype上的所有方法:toString、valueOf、hasOwnProperty等。

(4)Object.prototype.__proto__

console.log(null === Object.prototype.__proto__ ); // true

5、原型链

原型链,由原型对象组成的链式关系。因为每个对象都有原型,原型也是对象,也具有原型,这样一层一层往上链接,最后就构成了原型链。原型链最顶端(Object.prototype.__proto__)指向null。原型链的形成真正是靠_proto_ 而非prototype

6、总结

函数对象才有prototype属性,对象都有__proto__属性

  • 函数对象.__proto__ == Function.prototype

  • 实例.__proto__ == 构造函数.prototype

  • 实例.constructor == 构造函数

  • 构造函数.prototype == 构造函数.prototype

  • 构造函数.prototype.constructor == 构造函数

  • Function.__proto__ == Function.prototype

  • Function.constructor == Function

  • Function.prototype.__proto__ == Object.prototype

  • Object.prototype.__proto__ == null

    webp

    原型链

6、小练习

(1) new Foo().__proto__
(2) Foo.__proto__
(3) Foo.prototype.__proto__
(4) Object.__proto__



作者:家里有颗核桃树
链接:https://www.jianshu.com/p/1583f3036cf7


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消