构造函数、原型和原型链

构造函数

constructor 返回创建实例对象时构造函数的引用。 此属性的值时对函数本身的引用,而不是一个包含函数名称的字符串。

function Parent(){
	this.age = age
}

var p = new Parent(50)
p.constructor === Parent   // true
p.constructor === Object   // false

构造函数本身就是一个函数,与普通函数没有任何区别,不过为了规范一般将其首字母大写。构造函数和普通函数的区别在于,使用 new 生成实例的函数就是构造函数,直接调用的就是普通函数

symbol是构造函数吗

Symbol是基本数据类型,但作为构造函数来说它并不完整,因为它不支持语法 new Symbol(), Chrome认为其不是构造函数,如果要生成实例直接使用 Symbol() 即可。

new Symbol(123); // Symbol is not a constructor 

Symbol(123); // Symbol(123)

虽然是基本数据类型,但 Symbol(123)实例可以获取 constructor 属性值。

var sym = Symbol(123); 
console.log( sym );
// Symbol(123)

console.log( sym.constructor );
// ƒ Symbol() { [native code] }

这里的 constructor 属性其实是 Symbol 原型上的,即 Symbol.prototype.constructor 返回创建实例原型的函数,默认为Symbol函数。

手写一个new

function create() {
    // 创建一个空对象
    var obj = new Object()
    // 获得构造函数,arguments中取得第一个参数 
    Con = [].shift.call(arguments)
    // 链接到原型,obj可以访问到构造函数原型中的属性
    obj.__proto__ = Con.prototype
    // 绑定this实现继承,obj可以访问到构造函数中的属性
    var ret = Con.apply(obj, arguments)
    // 优先返回构造函数返回的对象
    return ret instanceof Object ? ret : obj
}

原型 prototype

每个对象拥有一个原型对象,对象以其原型为模板,从原型继承方法和属性,这些属性和方法定义在对象的构造器函数的prototype属性上,而非对象实例本身。
在这里插入图片描述

原型链

每个对象拥有一个原型对象,通过__proto__ 指针指向上一个原型,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向null。 这种关系被称为原型链,通过原型链一个对象会拥有定义在其他对象的属性和方法。
我们看下面一个例子。

function Parent(age) {
    this.age = age;
}

var p = new Parent(50);
p.constructor === Parent; // true

这里 p.constructor 指向 Parent,那是不是意味着 p 实例存在 constructor 属性呢?并不是。
我们打印一下P的值。
在这里插入图片描述
由图可以看出,实例对象p本身没有constructor属性,是通过原型链向上查找__proto__,最终查到constructor属性,该属性指向构造函数 Parent

function Parent(age) {
    this.age = age;
}
var p = new Parent(50);

p;	// Parent {age: 50}
p.__proto__ === Parent.prototype; // true
p.__proto__.__proto__ === Object.prototype; // true
p.__proto__.__proto__.__proto__ === null; // true

下图是原型链的运作机制。
在这里插入图片描述

小结

  • Symbol 作为构造函数来说并不完整,因为不支持语法 new Symbol(), 但其原型上拥有 constructor 属性,即 Symbol.prototype.constructor
  • 引用类型 constructor 属性值是可以修改的,但是对于基本类型来说是只读的,当然nullundefined 没有 constructor属性。
  • __proto__是每个实例上都有的属性, prototype是构造函数的属性,在实例上并不存在,所以这两个并不一样。但是 p.__prototypeParent.prototype 指向同一个对象。
  • __proto__ 属性在 es6 时被标准化,但因为性能问题并不推荐使用,推荐使用 Object.getPrototypeOf()
  • 每个对象拥有一个原型对象,通过__proto__指针指向上一个原型,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向null,这就是原型链。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值