外观
外观
耶温
1161字约4分钟
2024-05-11
构造函数创建一个Person
对象
function Person() {}
var person = new Person();
person.name = "Yevin";
console.log(person.name);
//输出:Yevin
Person 为一个构造函数
person 为一个实例对象,使用构造函数 Person 创建的
prototype
每个函数都有一个prototype
属性,指向该函数的原型对象
prototype
是函数才有的属性
function Person() {}
Person.prototype.name = "Yevin";
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);
console.log(person2.name);
//输出
//"Yevin"
//"Yevin"
函数的prototype
属性指向了一个对象,这个对象是调用该构造函数而创建的实例的原型。
也就是上面代码中 person1
与 person2
的原型
原型是什么:
每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型继承属性
继承:一般来说继承意味着复制操作,但是在Javascript中,继承并不会复制对象的属性,而是在两个对象中建立一个关联。相当于委托。
用一张图表示构造函数和实例之间的关系:
Person
:构造函数Person.prototype
:实例原型__proto__
每一个 JavaScript 对象(除了 null)都具有一个属性叫做
__proto__
,这个属性会指向该对象的原型
通过代码证明:
function Person() {}
person = new Person();
console.log(person.__proto__ === Person.prototype);
//输出 true
更新person
与构造函数Person
和实例原型Person.prototype
的关系图:
实例对象与构造函数都可以指向原型
constructor
constructor
:每一个原型都有一个constructor
属性指向关联的构造函数
验证方法:
function Person() {}
console.log(Person === Person.prototype.constructor);
//输出 true
因此再次更新person
与构造函数Person
和实例原型Person.prototype
的关系图:
//因此可知
function Person() {}
var person = new Person();
console.log(person.__proto__ == Person.prototype); //为True
console.log(Person.prototype.constructor == Person); //为True
console.log(Object.getPrototypeOf(person) === Person.prototype); // true
getPrototypeOf
:ES5 中的方法,可以获得对象的原型
当读取实例属性的时候,如果找不到该属性,就会自动查找与对象关联的原型中的属性,如果还查不到,就会去查找原型的原型,一直找到最顶层。
eg:
function Person() {}
Person.prototype.name = "wenbo";
var person = new Person();
person.name = "Yevin";
console.log(person.name); //Yevin
delete person.name;
console.log(person.name); // wenbo
当person
对象有name
属性时,打印输出的为person
对象中 name
属性的值。
当删除掉person
的name
属性时,打印时person
没有name
属性就会通过person
的原型也就是person.__proto__
或者Person.prototype
用来查找name
属性。
原型也是一个对象,可以通过最原始的方法构建
var obj = new Object();
obj.anme = "Yevin";
console.log(obj.name); //"Yevin"
原型对象就是通过
Object
构造函数生成的,结合上面所说,实例的__proto__
指向构造函数的prototype
更新关系图:
Object.prototype
的原型为null
验证:
console.log(Object.prototype.__proto__ === null); // true
null
标识'没有对象',即该处不应该有值
Object.prototype.__proto__
的值为null
,Object.prototype
没有原型
说明查找属性时查到Object.prototype
就可以停止查找了
最后更新关系图:
图中相互关联的原型组成的链状结构就是原型链,也就是红色这条线
constructor
属性:
function Person() {}
var person = new Person();
console.log(person.constructor === Person); //true
如上代码所示:
原因是因为获取person.constructor
时,person
没有constructor
属性,当不能读取到 constructor 属性时,会从person
的原型中读取,因此:
person.constructor === Person.prototype.constructor;
__proto__
:
绝大部分浏览器都支持这个非标准的方法访问原型,然后它并不存在于Person.prototype
中,实际上,他是来自Object.prototype
,与其说时一个属性,不如说是getter/setter
,当使用obj.__proto__
时,可以理解返回了Object.getPrototypeOf(obj)
。
继承:
继承意味着复制操作,然后 JavaScript 默认并不会复制对象的属性,相反 JavaScript 只是在两个对象之间建立一个关联,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫做继承,委托的说法更准确些。