JavaScript原型Prototype详情

目录
  • 1、概述
    • 1.1原型是什么
    • 1.2获取原型
  • 2、原型属性
    • 2.1利用原型添加属性与方法。
    • 2.2访问原型属性原型方法
  • 3、自有属性与原型属性
    • 3.1检测自有属性或者原型属性
  • 4、isPrototypeOf()方法
  • 5、扩展内置对象
  • 6、结语

1、概述

1.1原型是什么

JavaScript中,函数是一个包含属性和方法的Function类型的对象。而原型(Prototype )就是Function类型对象的一个属性。

在函数定义是包含了prototype属性,它的初始值是一个空对象 。在JavaScript中并没有定义函数的原始类型,所以原型可以是任何类型。

原型是用于保存对象的共享属性和方法的,原型的属性和方法并不会影响函数本身的属性和方法。

示例代码验证如下:

function fun() {
  console.log('函数原型')
}
console.log(fun.prototype) // {}

fun.prototype返回的也是一个空对象,但是这不说明Object.prototype中没有属性或者方法,这些属性和方法为不可枚举的,示例代码如下所示:

function fun() {
  console.log('函数原型')
}

console.log(fun.prototype) // {}
// 通过 Object.getOwnPropertyNames() 获取全部属性
console.log(Object.getOwnPropertyNames(fun.prototype)) // [ 'constructor' ]

其中,constructor属性指向该构造函数的引用,代码如下:

// constructor属性

console.log(fun.prototype.constructor) // [Function: fun]

console.log(fun.prototype.constructor === fun) // true

1.2获取原型

了解了原型的概念以及作用之后,我们需要获取到原型才能对其进行操作,在JavaScript中获取原型的方式有两种,如下所示:

通过构造函数的prototype属性。

通过Object.getPrototypeOf(obj)方法。

这两个的区别就是构造函数的prototype属性一般只配合构造函数使用,而Object.getPrototypeOf(obj)方法一般是获取构造函数实例化后的对象的原型方法。

实例代码如下:

// 构造函数
function Person(name) {
  this.name = name
}

// 指向构造函数的原型
var p1 = Person.prototype

var person = new Person('一碗周')

// 指向构造函数的原型
var p2 = Object.getPrototypeOf(person)

console.log(p1 === p2) // true

获取原型后可以跟操作对象似的进行操作,因为原型本身就是一个对象。

2、原型属性

JavaScript中,函数本身也是一个包含了方法和属性的对象。接下将学习函数对象的另一个属性——prototype,这个属性的初始值是一个空对象。

2.1利用原型添加属性与方法。

为对象添加属性和方法的另一种用法就是通过原型为其添加。当为一个构造函数添加原型属性和原型方法时,通过该构造函数new出的所有对象共享该属性和方法。

PS:所谓的原型属性或者原型方法就是通过原型添加的属性或者方法。

添加属性和方法的方式具有如下几种方式

直接为其增加属性或者方法

通过Object.defineProperty()方法,添加属性或者方法。这种方式比第一种方式更具有安全性。

直接添加对象到原型。

示例代码如下所示:

//构造函数
function Fun() {}
//直接为构造函数添加属性和方法
Fun.prototype.str = '这是一个字符串'
Fun.prototype.fn = function () {
  console.log('这是一个方法')
}
//通过 defineProperty 添加属性或者方法
Object.defineProperty(Fun.prototype, 'MyFun', {
  value: function () {
    console.log('this is MyFun')
  },
})
//测试
console.log(Fun.prototype.str)
Fun.prototype.fn()
Fun.prototype.MyFun()
var fun = new Fun()
fun.MyFun()
//直接为其定义个对象覆盖到之前的原型上
Fun.prototype = {
  name: '一碗周',
  fun: function () {
    console.log('this is function')
  },
}
Fun.prototype.fun()
var fun = new Fun()
fun.fun()

2.2访问原型属性原型方法

对于原型来说,最重要的一点就是它的实时性 。由于在JavaScript中,几乎所有的对象都是通过传引用的方式来传递的,因此我们所创建的的每个新对象实体中并没有一份属于自己的原型副本。这就意味着我们随时修改prototype属性,并且由同一构造器创建的所有对象的prototype属性也都会同时改变,包括我们之间通过构造器创建的属性和方法。

还是上面那段代码我们向原型中添加一个新方法,并调用,示例代码如下所示:

Fun.prototype.fn = function () {
  console.log('这是一个方法')
}
fun.fn() //这是一个方法

我们之前创建的对象可以访问新加的原型属性和原型方法。

3、自有属性与原型属性

我们先来创建一个构造函数,并为其添加两个原型属性。

//构造函数
function Fun() {}
//添加原型属性和方法
Fun.prototype.name = '一碗粥'
Fun.prototype.print = function () {
  console.log('this is function')
}

在通过该构造函数创建一个对象,为其设置属性和方法

//通过构造函数创建对象
var fun = new Fun()
//为对象添加属性和方法
fun.name = '一碗周'
fun.SayMe = function () {
  console.log('this is SayMe')
}

现在我们的fun对象,拥有自有属性/方法两个,原型属性/方法两个。我们依次来访问这些属性和方法。

//访问属性和方法
console.log(fun.name) // 一碗周
fun.SayMe() // this is SayMe
fun.print() // this is function

当我们访问name属性时,JavaScript引擎会遍历fun这个对象的所有属性,并返回name属性的值。SayMe()方法也是样的道理。但是到print()方法时,JavaScript引擎还是会遍历这个对象所有属性,这时就找不到一个叫print()方法了,接下来JavaScript引擎就会访问创建当前对象的构造器函数的原型,也就是我们的Fun.prototype,如果其中有该属性,则立即返回,否则返回undefined或者抛出异常

结论:当有自有属性时,优先访问自有属性,访问完自有属性再去访问原型属性 。

3.1检测自有属性或者原型属性

现在已经知道自有属性和原型属性的概念以及用途了,但是我们怎么知道一个属性时自由属性还是原有属性,JavaScript中提供以下两种方式来检测一个属性的情况

使用Object.prototype.hasOwnProperty(prop)方法来检测prop属性是否是自由属性,该方法返回一个布尔值,如果是自有属性则返回true,否则返回false。

来使用in关键字来检测对象以及原型链中是否具有指定属性。

测试代码如下:

// 通过Object.prototype.hasOwnProperty(prop)方法检测是否为自有属性
console.log(fun.hasOwnProperty('name')) // true
console.log(fun.hasOwnProperty('print')) // false
// 如果一个不存在的属性检测结果也是为false
console.log(fun.hasOwnProperty('SayMe')) // true

// 通过 in 运算符
console.log('name' in fun) // true
console.log('print' in fun) // true
console.log('SayMe' in fun) // true

通过测试我们发现,这两个方法并不能检测一个属性是不是一个自有属性或者原型属性,但是将这两个方法结合起来就可以检测是自有属性还是原型属性了,

示例代码如下:

function DetectionAttributes(obj, attr) {
  if (attr in obj) {
    if (obj.hasOwnProperty(attr)) {
      // 如果是自有属性属性返回1
      return 1
    } else {
      // 如果是原型属性返回0
      return 0
    }
  } else {
    // 没有这个属性返回 -1
    return -1
  }
}

测试如下:

console.log(DetectionAttributes(fun, 'name')) // 1
console.log(DetectionAttributes(fun, 'print')) // 0
console.log(DetectionAttributes(fun, 'SayMe')) // 1

4、isPrototypeOf()方法

isPrototypeOf()方法用来检测一个对象是否存在于另一个对象的原型链中,如果存在就返回true,否则就返回false。

实例代码如下所示:

// 定义一个对象,用于赋值给原型对象
var obj = function () {
  this.name = '一碗周'
}
var Hero = function () {} // 定义构造函数
// 将定义的对象赋值给构造函数的原型
Hero.prototype = obj

// 通过Hero创建对象
var hero1 = new Hero()
var hero2 = new Hero()
// 判断创建的两个对象是否在 obj 的原型链中
console.log(obj.isPrototypeOf(hero1)) // true
console.log(obj.isPrototypeOf(hero2)) // true

5、扩展内置对象

JavaScript中的内置对象有些也具prototype属性,利用内置对象的prototype属性可以为内置对象扩展属性和方法。

通过原型扩展内置对象的属性和方法非常灵活,根据个性化要求制定JavaScript语言的具体内容。

扩展内置对象的方式有两种,具体如下所示:

通过直接新增属性和方法。

通过Object对象的defineProperty()方法为其新增属性或者方法。这种方式会比第一种方式要好,是创建的属性和方法更具有安全性

示例代码如下所示:

// 为 Object 扩展属性和方法
// 使用第一种方式
Object.prototype.MyPrint = function () {
  console.log('this is MyPrint()')
}
// 使用第二种方式
Object.defineProperty(Object.prototype, 'MyInput', {
  value: function () {
    console.log('this is MyInput()')
  },
})
// 调用
Object.prototype.MyPrint() // this is MyPrint()
Object.prototype.MyInput() // this is MyInput()

6、结语

这篇文章介绍了JavaScript中的原型的概念、原型属性、如何检测自有属性和原型属性以及如何扩展内置对象

到此这篇关于JavaScript原型Prototype详情的文章就介绍到这了,更多相关JavaScript原型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • [js高手之路]图解javascript的原型(prototype)对象,原型链实例

    我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉. function CreateObj(uName) { this.userName = uName; } CreateObj.prototype.showUserName = function(){ return this.userName; } var obj1 = new CreateObj('ghostwu'); var obj2 = new CreateObj('卫庄')

  • JavaScript使用prototype原型实现的封装继承多态示例

    本文实例讲述了JavaScript使用prototype原型实现的封装继承多态.分享给大家供大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml&

  • js构造函数constructor和原型prototype原理与用法实例分析

    本文实例讲述了js构造函数constructor和原型prototype原理与用法.分享给大家供大家参考,具体如下: 所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型) 所有函数拥有prototype属性(显式原型)(仅限函数) 原型对象:拥有prototype属性的对象,在定义函数时就被创建 __proto__, prototype和constructor 下面这三个属性的定义非常重要,始终贯穿在原型中. prototype:此属性只有构造函数才有,它指向的是当前构造函数

  • js使用原型对象(prototype)需要注意的地方

    我们先来一个简单的构造函数+原型对象的小程序 function CreateObj( uName, uAge ) { this.userName = uName; this.userAge = uAge; } CreateObj.prototype.showUserName = function () { return this.userName; } CreateObj.prototype.showUserAge = function () { return this.userAge; } 这

  • javascript 对象 与 prototype 原型用法实例分析

    本文实例讲述了javascript 对象 与 prototype 原型用法.分享给大家供大家参考,具体如下: 我们做程序开发的,经常面对的就是一个一个对象.那么在javascript中我们怎么去创建一个类以及一个对象呢? <script type="text/javascript"> //创建一个Test对象 function Test(){ } var test = new Test(); //创建一个对象 var obj = new Object(); //json 对

  • JS原型prototype和__proto__用法实例分析

    本文实例讲述了JS原型prototype和__proto__用法.分享给大家供大家参考,具体如下: 先来看一个实例 function Foo() { } var foo = new Foo(); console.log(foo.prototype);// undefined console.log(foo.__proto__ === Foo.prototype);// true console.log(Foo.__proto__); [Function] Foo.__proto__结果如下: c

  • JavaScript原型Prototype详情

    目录 1.概述 1.1原型是什么 1.2获取原型 2.原型属性 2.1利用原型添加属性与方法. 2.2访问原型属性原型方法 3.自有属性与原型属性 3.1检测自有属性或者原型属性 4.isPrototypeOf()方法 5.扩展内置对象 6.结语 1.概述 1.1原型是什么 在JavaScript中,函数是一个包含属性和方法的Function类型的对象.而原型(Prototype )就是Function类型对象的一个属性. 在函数定义是包含了prototype属性,它的初始值是一个空对象 .在J

  • 在JavaScript实例对象中改写原型方法详情

    目录 在JavaScript中,我们通常可以像下面的代码这样来简单地定义一个类: var sample = function() { // constructor code here } sample.prototype.func1 = function() { // func1 code here } sample.prototype.func2 = function() { // func2 code here } /* more sample prototype functions her

  • JavaScript 原型与原型链详情

    目录 1.prototype(显式原型) 2.__proto__(隐式原型) 3.constructor(构造函数) 4.new的原理 5.原型链 5.1 原型链的作用 5.2 构造函数的__proto__是什么呢? 6.总结 前言: JavaScript常被描述为一种「基于原型的语言」--每个对象都拥有一个「原型对象」,对象以其原型为模板.从原型继承属性和放法.原型对象也可能拥有原型,并从中继承属性和方法,一层一层以此类推.这种关系常被称为「原型链」,它解释了为何一个对象会拥有定义在其他对象中

  • JavaScript为对象原型prototype添加属性的两种方式

    复制代码 代码如下: <script type="text/javascript"> <!-- /* 给原型 prototype 添加属性的两种方式 */ //方式一 var myObj = function(){ this.study = "JavaScript"; } myObj.prototype.hobby = function() { this.hobby = "See girl"; } var newObj = ne

  • 跟我学习javascript的prototype原型和原型链

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了,最近看了一些 JavaScript高级程序设计,终于揭开了其神秘面纱. 每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和

  • 深入学习JavaScript中的原型prototype

    javascript 是一种 prototype based programming 的语言, 而与我们通常的 class based programming 有很大 的区别,我列举重要的几点如下: 1.函数是first class object, 也就是说函数与对象具有相同的语言地位 2.没有类,只有对象 3.函数也是一种对象,所谓的函数对象 4.对象是按 引用 来传递的 那么这种 prototype based programming 的语言如何实现继承呢(OO的一大基本要素), 这也便是

  • JavaScript中的原型prototype属性使用详解

    prototype属性可以将属性和方法添加到任何对象(Number, Boolean, String 和Date等). 注:原型(Prototype)是一个全局的属性,它可以使用在几乎所有的对象. 语法 object.prototype.name = value 实例: 这里有一个例子展示了如何使用原型(prototype)属性的属性添加到对象: <html> <head> <title>User-defined objects</title> <sc

  • JavaScript设计模式之原型模式详情

    目录 前言 案例 回顾 原型的拓展 前言 设计模式呢最多的可能是用到类,我们去通过类来封装一些实用的方法,通过设计模式去实现各个方法之间的解耦等,由于JS中的继承是用原型链继承的,所以原型模式是用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法 案例 比如我们现在需要实现一个页面上的轮播图,可能需要用到对轮播图操作的方法,比如聚焦,切换,点击展开等动作,那么我们可以创一个图片轮播的方法,也可以叫做类 上面这个方法只是一个基础的方法,但在实际操作中我们可能会有不同的各种各

随机推荐