一、js中的两种对象,普通对象和函数对象

var obj1 = {};
var obj2 =new Object();
var obj3 = new obj1(); function fun1(){};
var fun2 = function(){};
var fun3 = new Function('str','console.log(str)');

第一种是普通对象,第二种是函数对象。上面两种对象三种情况,我们首先来分析一下对象,在js中如何实现面向对象思想,所谓的面向对象,对象基于模板来创建,首先定义一个类作为对现实世界的抽象,然后由类来实例化对象;而在原型语言中,对象以克隆另一个对象的方式创建,被克隆的母体称为原型对象。在上述代码中,第一行我们就申明了一个原型对象,也可以理解成面向对象中的“类”,然后我需要干什么?类式抽象的概念,但是我要使用这个类的方法或者属性,那么我们就需要实例化这个类,就是上述代码中的第三行。第二行则式一步完成了申明的同时进行实例化。有实例化对象的概念和“类”(原型对象)的概念接着来分析原型链,初始接触原型链的概念或许有点迷,但是我们要认清原型链,首先得知道他式干什么的,怎么来的。在我个人的理解中,原型链就是实例化对象使用他原型对象的方法属性的一条链子,实例化对象顺着这条链子找方法和属性,这么说或许不太准确,但是却很通俗易懂。说到这里,这条链子怎么找是有他自己的自己的规则的,你要用我就要按照我的规则来式吧,接下来了解一下原型链的规则。

二、创建对象

1、工厂函数模式

function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.getName = function () {
return this.name;
}
return o;//使用return返回生成的对象实例
}
var person = createPerson('Jack', , 'SoftWare Engineer');

创建对象交给一个工厂方法来实现,可以传递参数,但主要缺点是无法识别对象类型,因为创建对象都是使用Object的原生构造函数来完成的。

2、构造函数模式

function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.getName = function () {
return this.name;
}
}
var person1 = new Person('Jack', , 'SoftWare Engineer'); var person2 = new Person('Liye', , 'Mechanical Engineer');

这种模式创建对象,Person就是一个“类”的概念,没有事例之前本身只是一个概念,每一次实例化都需要使用new Person()来实例化一个新对象,将Person中的属性和方法赋予实例化对象person2,将函数的作用域赋给实例化对象,this指向实例化对象,并通过实例化过程中传参数,然后返回新对象。

和工厂函数模式不同,没有显式的创建对象,并且直接把属性和方法辅助给this对象。

这种模式创建对象时,很明显,我们每次实例化一个对象,都会把‘类’对象的上方法和属性全部赋给新对象并进行赋值,函数实例还不是一个作用域中,这样一般是没有问题的,只是会造成内存浪费。比如一个getName,我们并不需要每次都实例化一次,只要使用时能调用到它就可以了,当然我可以将getName函数在Person‘类’对象外定义,但是这样就没有起来封装的效果。

3、原型模式

JS每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,它是所有通过new操作符使用函数创建的实例的原型对象。原型对象最大特点是,所有对象实例共享它所包含的属性和方法,也就是说,所有在原型对象中创建的属性或方法都直接被所有对象实例共享。(注意是共享并不是赋值复制到本身!!!)

function Person(){
}
Person.prototype.name = 'Jack';//使用原型来添加属性
Person.prototype.age = ;
Person.prototype.getName = function(){
return this.name;
}
var person1 = new Person();
alert(person1.getName());//Jack
var person2 = new Person();
alert(person1.getName === person2.getName);//true;共享一个原型对象的方法

原型是指向原型对象的,这个原型对象与构造函数没有太大关系,唯一的关系是函数的prototype是指向这个原型对象!而基于构造函数创建的对象实例也包含一个内部指针为:[[prototype]]指向原型对象。这就意味着我们在上面的问题解决了,通过“类”对象事例化的新对象使用原型模式继承来的方法,新对象本身不具体这个方法,但是可以顺着这条链子(对象实例也包含一个内部指针为:[[prototype]]指向原型对象)去找“类”对象的原型对象中定义的方法,然后使用他。那么问题又来了,实例化多个方法后,这些所有的实例化对象的在原型对象上的方法和属性都是共享的,那么我们改变了他原型中的方法和属性,大家就会一起改变。无论是在原型对象上直接操作还是实例化对象通过原型“借用”方法和属性时改变,都会改变所有共享者和原型对象本身的方法和属性。

function Person() {
}
Person.prototype.name = 'Jack';
Person.prototype.lessons = ['Math','Physics'];
var person1 = new Person();
person1.lessons.push('Biology');
var person2 = new Person();
alert(person2.lessons);//Math,Physics,Biology,person1修改影响了person2

4、组合构造函数和原型模式

看完上面的同学估计也发现了,构造函数的不足之处被原型模式弥补了,原型模式的不足之恰好我门也可以用构造函数模式来解决,那么我们组合起来使用不就皆大欢喜了。

function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
Person.prototype = {
constructor: Person,//原型字面量方式会将对象的constructor变为Object,此外强制指回Person
getName: function () {
return this.name;
}
}
var person1 = new Person('Jack', , 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', , 'Mechanical Engneer');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法

上述代码中,我们用构造函数来给每个实例化对象实例化自己一个人使用属性,用原型模式来创建所有实例化对象一起共享的方法。而在我们实际使用中,jq的封装就式采用这种模式的。

5、动态模式

上述组合模式中已经解决了大部分问题,但是上述方法中,构造函数定义属性和原型对象定义共享方法是分离的,和面向对象不太符合。这种情况我们是否想到了我们上门第一个使用的方法工厂函数模型,我们将组合模式封装进工厂函数中。

function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
if (typeof this.getName != 'function') {//通过判断实例封装
  Person.prototype = {
    constructor: Person,//原型字面量方式会将对象的constructor变为Object,此外强制指回Person
    getName: function () {
      return this.name;
    }
  }
}
var person1 = new Person('Jack', , 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', , 'Mechanical Engneer');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法

在这个工厂函数中,所有实例化对象的属性式自己的,使用的原型对象方法会进行一个判断,如果原型对象上有这个方法,那么很好,我们直接用,如果没有呢,那么我们就给原型对象增加一个方法,再使用他。

以上纯属个人学习笔记。

代码和主题学习来自大大 https://www.cnblogs.com/shenjp/p/6517743.html

js原型和原型链理解到面向对象的更多相关文章

  1. js小记:对象、原型及原型链、面向对象编程

    一.js对象 1.js对象 js对象是一种复合数据类型,它可以把多个(不同类型的)数据集中在一个变量中,并且给每个数据起名字. 2.对象与数组 对象的每个数据有对应的名字(属性名),我们通过叫名字访问 ...

  2. JS基础-该如何理解原型、原型链?

    JS的原型.原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对 ...

  3. js原型链理解(2)--原型链继承

    1.原型链继承 2.constructor stealing(构造借用) 3.组合继承 js中的原型链继承,运用的js原型链中的__proto__. function Super(){ this.se ...

  4. 前端【JS】,深入理解原型和原型链

    对于原型和原型链,相信有很多伙伴都说的上来一些,但有具体讲不清楚.但面试的时候又经常会碰到面试官的死亡的追问,我们慢慢来梳理这方面的知识! 要理解原型和原型链的关系,我们首先需要了解几个概念:1.什么 ...

  5. Js中关于构造函数,原型,原型链深入理解

    在 ES6之前,在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但 ...

  6. JS原型、原型链深入理解

    原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 一.初识原 ...

  7. 理解js中的原型链

    对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 关于原型 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承 ...

  8. JS原型与原型链继承的理解

    一.原型 先从构造函数开始吧! 构造函数是什么?构造函数与其他函数唯一的区别在于调用方式不同.任何函数只要通过new来调用就可以作为构造函数,它是用来创建特定类型的对象. 下面定义一个构造函数 Fem ...

  9. 理解js中的原型,原型对象,原型链

    目录 理解原型 理解原型对象 实例属性与原型属性的关系 更简单的原型语法 原型的动态性 原型链 理解原型 我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象, ...

随机推荐

  1. turtlebot3 ubuntu mate 实现vnc连接

    tuutlebot3 ubuntu mate 实现vnc连接 摘要: 在turtlebot3 安装的nbuntu mate系统实验过. 实现内容 x11vnc 安装 x11vnc自动启动 vnc分辩率 ...

  2. (转) jmeter 获取cookie

      转自 https://blog.csdn.net/five3/article/details/53842283 jmeter是测试过程中会被用到的一个测试工具,我们即可用来进行压力的压测,也可以用 ...

  3. python查询数据库返回数据

    python查询数据库返回数据主要运用到flask框架,pymysql 和 json‘插件’ #!/usr/bin/python # -*- coding: UTF-8 -*- import pymy ...

  4. archlinux中安装Oracle12c的过程中遇到的问题

    INFO: : cannot find INFO: /usr/lib64/libpthread_nonshared.aINFO: INFO: genclntsh: Failed to link lib ...

  5. Java设计模式之动态代理

    关于Proxy: 1,他是所有动态代理的父类: 2,他可以用作创建动态代理类和动态代理对象: 3,JDK中自带的动态代理. 1,首先创建一个接口,方法申明如下: package com.proxy; ...

  6. [React Native] change port when running react native

    Two ways to do that. First, use this module to do that, https://github.com/ktonon/react-native-port- ...

  7. spring boot jpa 整合

    1,Eclipse JPA Tool配置 https://www.cnblogs.com/wgslucky/p/10109300.html 2,项目地址 https://gitee.com/wgslu ...

  8. 使用Redux DevTools浏览器插件调试redux

    与redux的Devtools模块不同,该工具主要依赖浏览器插件完成.模式也比Devtools简单点. step1 下载插件 Chrome地址(360极速模式也可以用): https://chrome ...

  9. PIL模块

    处理图片的模块 打开图片 im=Image.open("1.png") 创建字体对象 先要字体文件 font = ImageFont.truetype('C:\\WINDOWS\\ ...

  10. React脚手架create-react-app

    1.安装过程 $cnpm install -g -create-react-app $create-react-app apps $cd apps/ $npm start 2.图片路径 不能用相对路径 ...