32

JavaScript进阶笔记(五):构造函数、原型和原型链

 4 years ago
source link: https://www.tuicool.com/articles/uQjmyif
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

构造函数和普通函数没有区别,不同点是构造函数使用 new 来生成实例对象,直接调用就是普通函数。

注意:构造函数首字母通常大写。

1.1 Symbol 是构造函数吗?

Symbol 是基本数据类型,他不支持 new Symbol() 操作。

生成 Symbol 实例直接使用 Symbol() 即可。

虽然不是构造函数,但可以获取到 constructor 属性值。

var sym = Symbol('sym')
sym.constructor
// ƒ Symbol() { [native code] }

这个 constructor 是哪里来的?其实是 Symbol 原型上的。 Symbol.prototype.construnctor 返回创建实例原型的函数。

1.2 constructor 值是只读的吗?

分为两种情况:属性值为基本数据类型是只读。属性值为引用类型是可以修改的。

可以直接对 constructor 进行赋值。

new 的实现:

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

二、原型

JavaScript 是一种基于原型的语言 (prototype-based language),这个和 Java 等基于类的语言不一样。

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

function Person () {
    this.name = 'owenli'
    this.age = 12
}
Person.prototype.constructor === Person // true

构造函数有个指针指向原型,原型有个指针指向构造函数。

nAzqI3N.jpg!web

2.1 __proto__

在原型(Person.prototype)中有个 __proto__ 属性,它是访问器属性。通过它可以访问内部的 [[Prototype]][[Prototype]] 是对象的内部属性,外部代码无法直接访问。

var p = new Person()
p.__proto__ === Person.prototype // true

p.__proto__ 可以直接访问到对象的原型, __proto__ 是每个实例都有的属性。 prototype 是构造函数的属性。它们指向同一个对象。

3YbAfmy.jpg!web

注意: __proto__ 是 ES6 的标准,兼容性问题和性能问题,推荐使用 Object.getPrototypeOf() 。考虑性能问题,避免修改 [[prototype]]

如果创建一个新对象,同时继承另一个对象的 [[prototype]] ,推荐用 Object.create()

优化 new 的实现:

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

三、原型链

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

var p = new Person()
p.constructor === Person

p 实例也有 constructor ,并不是。实例本身是没有 constructor 属性的,是通过原型链向上查找 __proto__ ,最终查找到 constructor 属性,该属性指向 Person

p.constructor === Person //true
p.__proto__ === Person.prototype //true
p.__proto__.__proto__ === Object.prototype //true
p.__proto__.__proto__.__proto__ === null // true

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK