JavaScript基础之原型和原型链详解

普通对象和函数对象

let obj1 = {}
let obj2 = new Object()
let obj3 = new fun3()
let fun1 = function () {}
let fun2 = new Function('str', 'console.log(str)')
function fun3 () {}
console.log(typeof Object) //    function
console.log(typeof Function) //    function
console.log(typeof f1); //function 
console.log(typeof f2); //function
console.log(typeof f3); //function   
console.log(typeof obj1); //object 
console.log(typeof obj2); //object 
console.log(typeof obj3); //object

可以看出,上面的obj1, obj2, obj3都是普通对象,fun1,fun2,fun3为函数对象。凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。f2,f3,归根结底都是通过 new Function()的方式进行创建的。Function Object 也都是通过 New Function()创建的

构造函数

function Animal (name, age) {
    this.name = name
    this.age = age
    this.say = function () {
        console.log('我是个' + age + '的' + name)
    }
}
var cat = new Animal('cat', 49)
var dog = new Animal('dog', 2)

cat和dog都是Animal的实例,他们都有一个构造函数constractor属性,指向了Animal。即实例的构造函数属性指向构造函数。

console.log(cat.constructor == Animal)    //    true
console.log(dog.constructor == Animal)    //    true

原型对象

对于函数对象来说,每创建一个函数对象,都会有一个prototype属性,这个属性就是函数的原型对象。而每个对象,无论是函数对象,还是普通对象都会有一个__proto__属性。

function Aaimal () {}
Animal.prototype.name = 'cat'
let cat = new Animal()
consoel.log(cat.name)    // cat

原型对象:就是一个普通的对象:

function Animal () {}
Animal.prototype = {
    name: 'cat'
}

其实每一个原型对象,还会有一个默认的属性,就是constructor,这个属性指向原型对象的构造函数。

function Animal () {}
Animal.prototype = {
    name: 'cat'
}
console.log(Animal.prototype.constructor == Animal) //    true
let cat = new Animal()
console.log(cat.constructor == Animal)    //    true

所以原型对象(Animal.prototype)是构造函数的实例。而且我们可以看到原型对象都是普通对象,但是Function.prototype除外。他是函数对象,没有prototype。

 function Animal(){};
 console.log(Animal.prototype) //Animal{}
 console.log(typeof Animal.prototype) //Object
 console.log(typeof Function.prototype) // Function,这个特殊
 console.log(typeof Object.prototype) // Object
 console.log(typeof Function.prototype.prototype) //undefined

Function.prototype是函数对象的原因:

var A = new Function ();
Function.prototype = A;

原型对象的作用:原型对象的作用主要是用来实现继承的。

function Animal (name, age) {
    this.name = name
    this.age = age
}
Animal.prototype.say = function () {
    console.log('I am a' + this.age + '岁的' + this.name)
}
let cat = new Animal(1, 'cat')
cat.say()    // I am a 1岁的cat

所以,我们可以看到,在构造函数Animal的原型对象上添加say方法,然后cat实例就可以继承到Animal的属性。

__proto__:我们之前说过,无论是普通对象,还是函数对象,都会默认有一个__proto__属性。用于指向创建他的构造函数的原型对象。

function Animal () {}
let cat = new Animal()
console.log(cat.__proto__ == Animal.prototype)    //true

这种链接是存在于实例和构造函数的原型对象之间。而不是实例和构造函数之间。

构造器

创建对象的方式:

let obj = {}
let obj = new Object()

相当于是obj是Object的实例。那么也就是说:

obj.__proto__ == obj.constructor
obj.constructor == obj.prototype

创建对象的构造器不仅仅有 Object,也可以是 Array,Date,Function等。所以我们也可以构造函数来创建 Array、 Date、Function.

var b = new Array();
b.constructor === Array;
b.__proto__ === Array.prototype;

var c = new Date(); 
c.constructor === Date;
c.__proto__ === Date.prototype;

var d = new Function();
d.constructor === Function;
d.__proto__ === Function.prototype;

函数对象

JavaScript内置12个函数对象(其中Json是Es6中新增),Global不能直接访问,Arguments仅在函数调用时由JS引擎创建,Math,JSON是以对象形式存在的,无需new。它们的proto是Object.prototype。

Number.__proto__ === Function.prototype  // true
Number.constructor == Function //true

Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true

String.__proto__ === Function.prototype  // true
String.constructor == Function //true

// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Object.__proto__ === Function.prototype  // true
Object.constructor == Function // true

// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Function.__proto__ === Function.prototype // true
Function.constructor == Function //true

Array.__proto__ === Function.prototype   // true
Array.constructor == Function //true

RegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //true

Error.__proto__ === Function.prototype   // true
Error.constructor == Function //true

Date.__proto__ === Function.prototype    // true
Date.constructor == Function //true
Math.__proto__ === Object.prototype  // true
Math.construrctor == Object // true

JSON.__proto__ === Object.prototype  // true
JSON.construrctor == Object //true

所有的构造器都来自于 Function.prototype,甚至包括根构造器ObjectFunction自身。所有构造器都继承了·Function.prototype·的属性及方法。

总结:

对象分为普通对象,和函数对象。每个函数对象都有一个prototype属性,而无论普通对象还是函数对象都有一个__proto__属性。每个实例的__proto__指向构造函数的原型对象:

function Animal () {}
let cat = new Animal()
console.log(cat.__proto__ == Animal.prototype)

构造函数的原型对象的构造函数指向构造函数的原型:

function Animal () {}
Animal.prototype.constructor = Animal.prototype

实例的原型对象指向构造函数的原型对象:

function Animal () {}
let cat = new Animal()
Animal.prototype = Animal.prototype

完,TMD的绕了。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值