原型
原型是什么
- 所谓原型(Prototype)就是Function类型对象的一个属性
- 在函数定义时就包含了prototype属性,它的初始值是以个空对象.在JavaScript中并没有定义函数的原型类型,所以原型可以是任何类型
- 原型是用于保存对象的共享属性和方法的,原型的属性和方法并不会影响函数本身的属性和方法
示例代码:
// Function类型的属性 - 就是所有函数都具有的属性
console.log(Function.prototype);
// 定义函数
function fn() {
console.log('一花一世界');// 调用结果为 [Function]
}
// 原型的默认值是空对象
console.log(fn.prototype);// 调用结果为 fn {}
// 函数包含构造函数 - 就是所有引用类型其实都是构造函数
console.log(Number.prototype);// 调用结果为 [Number: 0]
console.log(Object.prototype);// 调用结果为 {}
var result = Object.getOwnPropertyDescriptor(Object.prototype,'constructor');
console.log(result);
获取原型
- 可以通过两种方式获取原型,从而设置共享的属性和方法
1. 通过构造函数的prototype属性
示例代码:
function fn() {
console.log('一花一世界');
}
// 使用访问对象的属性语法结构
console.log(fn.prototype);// 调用结果为 fn {}
console.log(fn['prototype']);// 调用结果为 fn {}
2. 通过Object对象的getPrototypeOf()方法
示例代码:
// Object类型提供getPrototypeOf()方法
function fn() {
console.log('一花一世界');
console.log(Object.getPrototypeOf(fn));// 调用结果为 [Function]
为原型新增属性或方法
示例代码:
function fn() {
console.log('一花一世界');
}
// 变量proto也是一个空对象
//var proto = fn.prototype;
//console.log(proto);// 调用结果为 fn {}
//新增属性或方法
// 1. prototype.name = '小燕子';
fn.prototype.name = '小燕子';
console.log(fn.prototype);// 调用结果为 fn { name: '小燕子' }
// 2. defineProperty() - 表示定义属性
Object.defineProperty(fn.prototype,'age',{
value : 21 + '岁',
/* 可枚举 */
enumerable : true
});
console.log(fn.prototype);// 调用结果为 fn { name: '小燕子', age: '21岁' }
构造函数的原型
示例代码:
// 定义构造函数
function Hero() {
this.name = '一花一世界';
this.sayMe = function () {
console.log('花花世界');
}
}
// 操作构造函数Hero的原型
Hero.prototype.age = 26;
// 利用构造函数来创建对象
var hero = new Hero();
console.log(hero);// 调用结果为 Hero { name: '一花一世界', sayMe: [Function] }
// 为构造函数的原型新增的属性 - 构造函数创建的对象中依旧可以访问
console.log(hero.age);// 调用结果为 26
// 对象hero中不存在age属性
// getOwnPropertyDescriptor - 表示获取私有属性描述符
var result = Object.getOwnPropertyDescriptor(hero,'age');
console.log(result);// 调用结果为 undefined
代码分析图:
自有属性与原型属性
- 自有属性 - 通过对象的引用添加的属性.其它对象可能无此属性;即使有,也是彼此独立的属性
- 原型属性 - 从原型对象中继承来的属性,一旦原型对象中属性值改变,所有继承自该原型的对象属性性均改变
示例代码:
// 定义构造函数
function Hero(name) {
// 构造函数本身的属性 - 自有属性
this.name = name;
this.sayMe = function () {
console.log('一花一世界');
}
}
// 通过构造函数Hero的prototype新增属性或方法
// 通过原型所定义的属性 - 原型属性
Hero.prototype.age = 26;
/*
通过构造函数Hero创建对象时
* 不仅具有构造函数的自有属性
* 还具有构造函数的原型属性
*/
var hero = new Hero('花花世界');
console.log(hero.name);//调用结果为 花花世界
console.log(hero.age);//调用结果为 26
var hero2 = new Hero('一笑一人生');
console.log(hero2.name);//调用结果为 一笑一人生
console.log(hero2.age);//调用结果为 26
// 为对象hero新增age属性
hero.age = 62;
console.log(hero.age);// 调用结果为 62
console.log(hero);// 调用结果为 Hero { name: '花花世界', sayMe: [Function], age: 62 }
console.log(hero2.age);//调用结果为 26
Hero.prototype.age = 77;
console.log(hero.age);// 调用结果为 62
console.log(hero2.age);// 调用结果为 77
重写属性
- 通过构造函数或对象的自有属性可以重写原型的属性
示例代码:
// 定义构造函数
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)方法
- 作用 - 判断当前指定属性是否为自有属性
- 参数 - prop - 表示指定属性名称
-
返回值 - 布尔值
- true - 表示存在指定的自有属性
- false - 表示不存在指定的自有属性
-
使用in关键字检测对象的属性
- 作用 - 判断对象中是否存在指定属性(自有属性或原型属性)
-
返回值 - 布尔值
- true - 表示存在指定的属性
- false - 表示不存在指定的属性
示例代码:
function Hero() {
//this.name = '醉影笑惊鸿'// 自有属性
}
//Hero.prototype.name = '花花世界';
var hero = new Hero();
/*
Object.hasOwnProperty(prop)方法
* 作用 - 判断当前指定属性是否为自有属性
* 参数
* prop - 表示指定属性名称
* 返回值 - 布尔值
* true - 表示存在指定的自有属性
* false - 表示不存在指定的自有属性
*/
console.log(hero.hasOwnProperty('name'));
/*
使用in关键字检测对象的属性
* 作用 - 判断对象中是否存在指定属性(自有属性或原型属性)
* 返回值 - 布尔值
* true - 表示存在指定的属性
* false - 表示不存在指定的属性
*/
console.log('name'in hero);
控制台效果对比图:
操作原型的方式
1. 利用对象.属性或方法的方式新增属性或方法
示例代码:
// 定义构造函数
function Hero() {}
// 通过构造函数的原型新增属性或方法
Hero.prototype.name = '一花一世界';
Hero.prototype.sayMe = function () {
console.log('醉影笑惊鸿');
// 通过构造函数创建对象
var hero = new Hero();
console.log(hero.name);//调用结果为 一花一世界
hero.sayMe();//调用结果为 醉影笑惊鸿
2. 将原型重新赋值为一个新对象
示例代码:
// 定义构造函数
function Hero() {}
// 通过构造函数的原型新增属性或方法
Hero.prototype = {
name : '一笑一人生',
sayMe : function () {
console.log('极乐世界');
}
};
// 通过构造函数创建对象
var hero = new Hero();
console.log(hero.name);//调用结果为 一笑一人生
hero.sayMe();//调用结果为 极乐世界
显示原型与隐式原型
-
所有对象其实也具有原型
- 注意 - 对象的原型(__proto__)并非是函数的原型(prototype)
-
区分:
- 将函数的原型 -> 显式原型
- 将对象的原型 -> 隐式原型
-
对象的原型
- 不能用于真实开发工作,仅用于逻辑测试
- 注意: __proto__属性只能在调用时使用. __proto__属性与prototype属性并不等价.
示例代码:
// 定义构造函数
function Hero() {
this.name = '皮卡丘';
}
// 通过构造函数的原型新增属性或方法
Hero.prototype.age = 26;
// 通过构造函数创建对象
var hero = new Hero();
console.log(hero.name);// 对象调用自有属性 结果为 皮卡丘
console.log(hero.age);// 对象调用原型属性 结果为 26
/*
所有对象其实也具有原型
* 注意 - 对象的原型(__proto__)并非是函数的原型(prototype)
* 区分
* 将函数的原型 -> 显式原型
* 将对象的原型 -> 隐式原型
* 对象的原型
* 不能用于真实开发工作,仅用于逻辑测试
*/
console.log(hero.prototype);// 调用结果为 undefined 表示对象中不存在该属性
console.log(hero.__proto__);// 调用结果为 Hero { age: 26 }
isPrototypeOf()方法
- 每个对象中都会具有一个isPrototypeOf()方法,该方法用来判断一个对象是否是另一个对象的原型
示例代码:
// 通过初始化器方式定义对象
var obj = {
name : '皮卡丘'
}
// 定义构造函数
function Hero(){}
// 将对象obj赋值给构造函数Hero的原型
Hero.prototype = obj;
// 通过构造函数创建对象
var hero = new Hero();
// 判断指定对象是否是另一个对象的原型
var result = obj.isPrototypeOf(hero);
console.log(result);// 调用结果为 true - 表示是另一个对象的原型
扩展内置对象
- 通过原型扩展内置对象的属性和方法非常灵活, 根据个性化要求定制JavaScript语言的具体内容
- 注意: 一般不建议使用这种方式,如果JavaScript的版本更新时可能会提供个性化的属性或方法,会导致冲突
示例代码:
Object.prototype.sayMe = function(){
console.log('一花一世界');
}
// 通过Object构造函数创建对象
var obj = new Object();
obj.sayMe();// 调用结果为 一花一世界
Array.prototype.inArray = function(color){
// this - 表示当前的数组
for(var i = 0, len = this.length; i < len; i++){
if(this[i] === color){
return true;
}
}
return false;
}
var arr = ["red", "green", "blue"];
console.log(arr.inArray("red"));// 调用结果为 true
console.log(arr.inArray("yellow"));// 调用结果为 false
扩展内置对象补充
示例代码:
/* 定义对象原型属性 */
Object.defineProperty(Object.prototype, 'sayMe', {
/* 函数方法 */
value : function(){
/* 函数体 */
console.log('一花一世界');
}
});
/* 定义变量并赋值新创建的对象 */
var obj = new Object();
/* 调用创建的函数属性 */
obj.sayMe();// 调用结果为 一花一世界
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。