Javascript之深入浅出prototype

我们先来讲一个故事,一个大大的池塘,里面有很多鱼。这是属于我们大家的池塘所以里面的鱼我们都可以吃,但是我们也会从集市买一些鱼放在家里,那么放在家里的鱼肯定是属于我们私人的,外人是不会拥有的。那么在js里我们就把这个池塘称为原型对象,池塘里面我们所共享的鱼称为原型中的属性及方法,而我们自己的鱼称为构造函数中的属性及方法,我们是什么呢?对了,我们是对象的实例

以上是为了让大家能够趣味性的对prototype有一个概念,接下来就通过代码具体总结一下prototype~

一、理解prototype

我们创建的每一个函数都有一个prototype属性,这个属性是一个指向对象的指针。

构建对象中有一种模式叫做原型模式,意思是将对象实例所不可共享的属性及方法定义在构造函数中,而将可共享的属性及方法放在原型对象中,也就是prototype指向的对象中。以下是用原型模式创建的一个对象:

 function person(name, age) {
 this.name = name;
 this.age = age;
}
person.prototype = {
 sayName: function() {
 console.log(this.name);
 }
};
var p1 = new person("Wind", 20);
p1.sayName(); // "Wind"
var p2 = new person("Nic", 20);
p2.sayName(); // Nic

这里我将name、age属性定义在构造函数中,将sayName方法定义在原型中。所以p1和p2对象实例的内存空间里面各有一份name和age,但是它们却共享一份sayName方法,意思是它们调用的sayName方法是同一个。

试想如果我们不用prototype,而是直接将sayName写进构造函数呢?

那么p1和p2中将各有一份sayName,这样浪费内存空间,所以用prototype的好处之一:提高了代码的复用性,减少内存

在了解原型对象的同时我们还有一个小知识要明白:每当代码读取一个对象属性的时候会执行一次搜索,搜索目标是给定名字的属性,搜索路径为:

对象实例本身---->原型对象---->对象所继承的父类对象---->父类对象原型...---->原型链末端

二、prototype的注意点

1、不可变性:尽管prototype是共享的,但不能通过对象实例重写原型中的值,但是可以由对象统一改。通俗一点:只能爸爸统一改,不能儿子改。(这也和类型有关系,孩子不能改变基本类型的值,但是可以改变对象,比如数组)

基本类型:

function person() {}
person.prototype = {
 num: 0
};
var p1 = new person();
var p2 = new person();
p1.num++;
p2.num; // 0

非基本类型:

function person() {}
person.prototype = {
 num: [1,2,3]
};
var p1 = new person();
var p2 = new person();
p1.num[2] = 8;
p2.num; // [1, 2, 8] 改变了

2、同名覆盖性:如果我们在实例中添加了一个与原型属性同名的属性,那么该属性会创建到对象实例中并且会覆盖掉原型中的相应属性。

function person(name) {
 this.name = name;
}
person.prototype = {
 age: 18 9 };
var p1 = new person("Wind");
var p2 = new person("Nic");
p1.age = 20;
p1.age; // 20
p2.age; // 18

3、使用对象字面量创建原型方法,会切断之前的链而重写原型链

function person(name) {
 this.name = name;
}
person.prototype = {
 sayName: function() {
 console.log(this.name);
 }
};
var p1 = new person("Wind");
person.prototype = {
 age = 20
};
p1.sayName(); // error

因为prototype指针指向了一个新的对象,切断了构造函数与之前的prototype旧对象的联系,所以p1不能调用了它。那么p1调用新对象的属性呢?

p1.age; // error

所以我做了一个大胆的猜测,就是以前包含sayName的旧对象被“抛弃”了,也就是被内存回收了,然而p1的prototype指针指向的依旧是旧对象,所以会产生error。

三、总结

prototype的用法:构造函数模型用于定义实例的属性,而原型模型用于定义方法和共享的属性。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • js中prototype用法详细介绍

    prototype 是在 IE 4 及其以后版本引入的一个针对于某一类的对象的方法,而且特殊的地方便在于:它是一个给类的对象添加方法的方法!这一点可能听起来会有点乱,别急,下面我便通过实例对这一特殊的方法作已下讲解: 首先,我们要先了解一下类的概念,JavaScript 本身是一种面向对象的语言,它所涉及的元素根据其属性的不同都依附于某一个特定的类.我们所常见的类包括:数组变量(Array).逻辑变量(Boolean).日期变量(Date).结构变量(Function).数值变量(Number)

  • JQuery,Extjs,YUI,Prototype,Dojo 等JS框架的区别和应用场景简述

    所以Javascript已经成为了web开发最最基本的要求之一了. 而在现实的敏捷开发中,我们通常会选择一个JS框架来取代繁琐的Native Javascript的编写.你会发现这样会节省很多的时间,写的代码也很清晰便捷.(当然在学生时代的是有也质疑过,用框架会对原生态的 Javascript理解不深入,其实这是多虑了的.在对框架的深入的同时,对原生的js也会理解的更透彻一些.成为一个精明的开发者,两者是相依相偎的.而最好的状态就是想Qzone前端一样,完全按照自己的需求开发出一套JS,CSS框

  • JavaScript prototype 使用介绍

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

  • Javascript中prototype的使用详解

    先看下面一段代码: function Machine(ecode, horsepower) { this.ecode = ecode; this.horsepower = horsepower; } function showme() { alert(this.name + " " + this.ecode + " " + this.horsepower); } var machine = new Machine("code1", 15); ma

  • 详解Javascript中prototype属性(推荐)

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于'类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能

  • js中继承的几种用法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 复制代码 代码如下: <SPAN style="BACKGROUND-COLOR: #ffffff"><SPAN style="FONT-SIZE: 18px"><html>  <body>  <script type="text/javascript">      function Person(na

  • JavaScript中的prototype使用说明

    1.prototype 在JavaScript中并没有类的概念,但JavaScript中的确可以实现重载,多态,继承.这些实现其实方法都可以用JavaScript中的引用和变量作用域结合prototype来解释. 2.简单的例子 复制代码 代码如下: var Blog = function( name, url ){ this.name = name; this.url = url; }; Blog.prototype.jumpurl = ''; Blog.prototype.jump = fu

  • js中使用使用原型(prototype)定义方法的好处详解

    经常在前端面试或是和其他同行沟通是,在谈到构造在JS定义构造函数的方法是最好使用原型的方式:将方法定义到构造方法的prototype上,这样的好处是,通过该构造函数生成的实例所拥有的方法都是指向一个函数的索引,这样可以节省内存. 当然,这种说法没有任何问题,只是在实现上,并非只有使用prototype的方式才能达到这样的效果,我们可以将方法以函数的形式定义在构造函数之外,然后在构造函数中通过this.method = method的方式,这样生成的实例的方法也都通过索引指向一个函数,具体如下:

  • JavaScript中的原型prototype完全解析

    要理解JS中的prototype, 首先必须弄清楚以下几个概念    1. JS中所有的东西都是对象 2. JS中所有的东西都由Object衍生而来, 即所有东西原型链的终点指向Object.prototype // ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf&q

  • JS构造函数与原型prototype的区别介绍

    构造函数方法很好用,但是存在一个浪费内存 通过原型法分配的函数是所有对象共享的. 通过原型法分配的属性是独立.-----如果你不修改属性,他们是共享 如果我们希望所有的对象使用同一一个函数,最好使用原型法添加函数,这样比较节省内存. 例子: //----构造函数模式 为Cat对象添加一个不变的属性"type"(种类),再添加一个方法eat(吃老鼠).那么,原型对象Cat就变成了下面这样: <script> function Cat(name, color) { this.n

随机推荐