叉烧店并不卖叉烧

javascript-original-object-prototype

javascript TTT 38℃ 0评论

参考

我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法

引用类型才具有prototype属性,包含:

  • 1.Object
  • 2.Function
  • 3.Array
  • 4.Date
  • 5.String
  • 6.RegExp

例如:

var fn = new String("text");
console.log(fn); //[object String]: {0: "t", 1: "e", 2: "x", 3: "t", length: 4}
console.log(fn.value); //undefined
String.prototype.value="val"; 
console.log(fn.value); //val
function Person(name){
    this.name = name;
}
Person.prototype.getName = function () {
    return this.name;
};
var p1 = new Person("Evan"); 
console.log(p1.name); // Evan
console.log("next line");
console.log(p1.getName()); // Evan

这个prototype属性也就相当于动态添加了属性或者方法

例子:

function Person2 () {
}
Person2.prototype.name = "Nicholas";
Person2.prototype.age = 29;
Person2.prototype.job = "Software Engineer";
Person2.prototype.sayName = function () {
    console.log(this.name)
};
var p2 = new Person2();
var p3 = new Person2();
p2.sayName(); // Nicholas
console.log(p2.sayName == p3.sayName); // true

一张图看各个对象的关系:

图中的Person为代码的Person2

Person2里面只有一个prototype属性,指向原型对象(原型对象顾名思义就是每次用Person2去实例化一个对象的时候,都是有基于原型对象,使用prototype为Person2添加属性和方法就是为Person2的原型对象去添加属性和方法)。原型对象中的constructor指向它的构造函数(它的来源,也就是Person2),和其他原型属性和方法。

Person2.prototype就是原型,isPrototypeOf确定二者是否有关系,Object.getPrototypeOf获取原型值

console.log(Person2.prototype); // {age: 29, constructor: function Person2() { }, job: "Software Engineer", name: "Nicholas", sayName: function () { console.log(this.name) }}
console.log(Person2.prototype.isPrototypeOf(p2)); // true
console.log(Object.getPrototypeOf(p2).name); // Nicholas
console.log(Person2.prototype.constructor == Person2); // true

将上例稍微改一下,给实例化的P2添加name属性并赋值:name: me

p2.name = "me";
// 现在实例中找,没有再到原型中找
console.log(p2.name); // 
console.log(p2.constructor == Person2); // true
// 用hasOwnProperty()检测属性或者方法是否在实例中(也就是当前对象Person2所拥有,而非原型对象Person2.prototype)
console.log(p2.hasOwnProperty("name")); // true
console.log(p3.hasOwnProperty("name")); // false
// 用一个in,检测是否有次属性(也就是查找自身对象,原型对象和原型对象中的原型对象),无论在实例还是原型对象中
console.log("name" in p2); // true
console.log("name" in p3); // true

若改整个Person2.prototype:

// 这是在Chrome浏览器实现的,在IE和edge表现不同
Person2.prototype = {xx: "xx"};
console.log(p2.xx); // undefined
var ppp = new Person2();
console.log(ppp.xx); // xx

只会改变后面的实例的对象,之前的不会改变。之前引用的不会被垃圾清理。(这是在Chrome浏览器钟进行的试验,IE和Edge有不同的表现)

p2和p3是实例化的Person2,也能访问Person2的原型对象。Person2用指针[[Prototype]]来实现访问原型对象。p2和p3不能操作[[Prototype]],但可以用__proto__来访问

console.log("========");
console.log(p1.prototype); // undefined
console.log(Person2.prototype); // {name: "Nicholas", age: 29, job: "Software Engineer", sayName: ƒ, constructor: ƒ}
console.log(p2.__proto__); // {name: "Nicholas", age: 29, job: "Software Engineer", sayName: ƒ, constructor: ƒ}
console.log(Person2.__proto__); // ƒ () { [native code] }

实例化对象调用原型对象是使用__proto__指针,而不是prototype指针。对象本身没有原型对象,是去调用构造函数的原型对象

当构造函数Person2调用__proto__,返回它本身

__proto__prototype的区别:(IE不支持__proto__)

  • __proto__:对象的内部原型的引用
  • prototype:返回类的原型

当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就回去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就会这个一直找下去,也就说我们平时所说的原型链的概念。所以__proto__是联系各个对象的桥梁

var Person3 = function () {};
var p4 = new Person3();
console.log(p4.__proto__ == Person3.prototype); // true

上面的例子,实例p4的来源(__proto__)就是Person3的原型(prototype)

转载请注明:叉烧店 » javascript-original-object-prototype

喜欢 (0)
发表我的评论
取消评论

CAPTCHA Image
Reload Image
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址