在 Javascript中,函数是一个包含属性和方法的Function类型的对象。而原型( Prototype)就是Function类型对象的一个属性。
在函数定义时就包含了 prototype属性,它的初始值是一个空对象。在 Javascript中井没有定义函数的原型类型,所以原型可以是任何类型。
原型是用于保存对象的共享属性和方法的,原型的属性和方法并不会影响函数本身的属性和方法。
原型的默认值是空对象,所有引用类型都是构造函数,所有函数都具有prototype
属性。
// Function 类型的属性 -> 所有函数都具有的属性 console.log(Function.prototype); function fn() { console.log("this is function"); } // 原型的默认值是空对象 console.log(fn.prototype); // 函数包含构造函数 -> 所有引用类型都是构造函数 console.log(Number.prototype); console.log(Object.prototype); var result = Object.getOwnPropertyDescriptor(Object.prototype, "constructor"); console.log(result);
获取原型的方式有两种
使用访问对象的属性语法结构
function fn() { console.log("this is function "); } // 使用访问对象的属性语法结构 console.log(fn.prototype); // fn {} console.log(fn["prototype"]); // fn {}
Object类提供的getPrototype()方法
function fn() { console.log("this is function "); } console.log(Object.getPrototypeOf(fn)); //[Function]或者ƒ () { [native code] }
第二种方式中,在nodejs环境中会打印[Function]
而在浏览器会打印ƒ () { [native code] }
使用对象新增方式。
function fn() { console.log("this is function "); } // 新增属性或方法 fn.prototype.name = "张无忌"; console.log(fn.prototype.name); // 张无忌 console.log(fn.prototype); // fn { name: '张无忌' }
使用defineProperty()方法
function fn() { console.log("this is function "); } // defineProperty() Object.defineProperty(fn.prototype, "age", { value: 10, // 如果不修改此属性描述符,则不可枚举 enumerable: true, }); console.log(fn.prototype); // fn {age: 10 }
// 定义构造函数 function Hero() { this.name = "张无忌"; this.sayMe = function () { console.log("this is function "); }; } // 操作构造函数Hero的原型 Hero.prototype.age = 18; // 利用构造函数来创造对象 var hero = new Hero(); console.log(hero); // Hero { name: '张无忌', sayMe: [Function] } // 为构造函数的原型新增的属性在创建对象中仍然可以访问 console.log(hero.age); // 18 // 对象小hero中不存在age属性 var result = Object.getOwnPropertyDescriptor(hero, "age"); console.log(result); //undefined
以上代码经测试可以发现,为构造函数原型新添加的属性,在其对象中虽可访问但通过getOwnPropertyDescriptor
方法是得不到的。
通过构造函数Hero创建对象时不仅具有构造函数的自有属性,也具有构造函数的原型属性。
通过对象是无法修改原型的值,修改原型的值,必须修改构造函数的原型。
// 定义一个构造函数 function Hero(name) { // 构造函数本身的属性 成为自有属性 this.name = name; this.sayMe = function () { console.log("this is function"); }; } // 通过构造函数Hero的prototype新增属性或方法 // 通过原型所定义的属性称为原型属性 Hero.prototype.age = 19; /** * 通过构造函数Hero创建对象时 * 不仅具有构造函数的自有属性 * 也具有构造函数的原型属性 * */ var hero = new Hero("张无忌"); console.log(hero.name); // 张无忌 console.log(hero.age); //19 var hero2 = new Hero("周芷若"); console.log(hero2.name); // 周芷若 console.log(hero2.age); //19 hero.age = 80; // 相当于为hero新增属性 console.log(hero); console.log(hero.age); //80 console.log(hero2.age); // 19 Hero.prototype.age = 80;
自有属性的优先级高于原型属性,也就是说当原型属性与自有属性同时存在时,那么优先打印出的是自有属性。但自有属性不会覆盖原型属性,当删除自有属性时,再次访问该属性,那么会输出原型属性。
// 定义构造函数 function Hero() { this.name = "张无忌"; } // 构造函数的原型 Hero.prototype.name = "周芷若"; // 构造函数创建对象 var hero = new Hero(); // 自有属性与原型同名时,默认访问的是自有属性 // 自有属性的优先级别高于原型属性 console.log(hero.name); //张无忌 // 删除对象的属性 delete hero.name; console.log(hero.name); //周芷若
检测自有属性有两种方式,分别为object.hasOwnProperty(prop)
与in
关键字。但这两种方式是有区别的。
object.hasOwnProperty(prop)
方式
true
表示存在指定属性是自有属性false
表示不存在指定的自有属性function Hero() { this.name = "张无忌"; // 自有属性 } Hero.prototype.age = 18; var hero = new Hero(); /** * object.hasOwnProperty() * 作用 - 判断当前属性是否为自有属性 * 参数 * prop - 表示指定属性的名称 * 返回值 * true - 表示存在指定属性是自有属性 * false - 表示不存在指定的自有属性 */ console.log(hero.hasOwnProperty("name")); //true console.log(hero.hasOwnProperty("age")); // false console.log(hero.hasOwnProperty("sex")); // false
in
关键字
true
表示存在指定属性false
表示不存在指定属性function Hero() { this.name = "张无忌"; // 自有属性 } Hero.prototype.age = 18; var hero = new Hero(); /** * 使用in关键字检测对象的属性 * 作用 - 判断对象中是否存在指定属性(自有属性或原型属性) * * 返回值 * true - 表示存在指定属性 * false - 表示不存在指定属性 */ console.log("name" in hero); //true console.log("age" in hero); //true console.log("sex" in hero); // false
function Hero() {} // 1. 利用对象.属性或方法的方式新增属性或方法 Hero.prototype.name = "张无忌"; Hero.prototype.sayMe = function () { console.log("this is function"); }; var hero = new Hero(); console.log(hero.name); // 张无忌 hero.sayMe(); // this is function
function Hero() {} // 2. 直接将原型重新赋值为一个新对象 Hero.prototype = { name: "张无忌", sayMe: function () { console.log("this is function"); }, }; var hero = new Hero(); console.log(hero.name); // 张无忌 hero.sayMe(); // this is function
将函数的原型称为显式原型
将对象的原型成为隐式原型
所有对象都具有原型,但对象的原型(__proto__)并非是函数的原型(prototype)。对象的原型不能用于真实开发工作,仅用于逻辑测试
// 定义构造函数 function Hero() { this.name = "张无忌"; } // 通过构造函数的原型新增属性或方法 Hero.prototype.age = 18; // 通过构造函数创建对象 var hero = new Hero(); console.log(hero.name); console.log(hero.age); /** * 所有的对象其实也具有原型 * * 注意 - 对象的原型(__proto__)并非是函数的原型(prototype) * 区分 将函数的原型称为 显式原型 将对象的原型成为 隐式原型 * 对象的原型:不能用于真实开发工作,仅用于逻辑测试 */ console.log(hero.prototype); // undefined 表示对象中不存在该属性 console.log(hero.__proto__); // Hero { age: 18 }
isPrototypeOf() 判断指定对象是否是另一个对象的原型。
// 通过初始化器定义对象 obj = { name: "张无忌", }; // 定义构造函数 function Hero() {} // 将对象obj赋值给构造函数Hero的原型 Hero.prototype = obj; // 通过构造函数创建对象 var hero = new Hero(); // isPrototypeOf() 判断指定对象是否是另一个对象的原型 console.log(obj.isPrototypeOf(hero)); // true console.log(hero.isPrototypeOf(obj)); // fasle
Object.prototype.sayMe = function () { console.log("this is function"); }; // 通过Object构造函数创建对象 var obj = new Object(); obj.sayMe();
defineProperty
方法新增Object.defineProperty(Object.prototype, "sayMe", { value: function () { console.log("this is sayMe"); }, }); var obj = new Object(); obj.sayMe();
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句