一、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. javascript的ES6学习总结(第一部分)

    ES6(ESNext学习总结——第一部分) ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版. ECMA每年6月份,发布一个版本 201 ...

  2. 【JVM】-NO.113.JVM.1 -【JDK11 HashMap详解-4-resize()】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  3. 安卓微信端打开H5页面背景图被键盘挤压移动位置解决

    问题:在微信端(安卓浏览器也如此)打开的H5登录页面中,点击输入信息,弹出软键盘会挤压背景图片. 本来的body宽高设置body{width:100%,height:100%},不起作用,这样写就会导 ...

  4. 解决IE浏览器把application/json响应视为文件并尝试下载

    下面我的解决方案是针对.net MVC的,其他的解决方案也类似,就是把响应的mimeType换成IE浏览器已经拥有的.如application/json换成text/plain #region 退出登 ...

  5. Scrapy详解

    一.爬虫生态框架 在管道传数据只能传字典和items类型. 将 上一return语句注释则会报错  如: 如上图,爬虫文件中有一个name属性,如果多个爬虫可以通过这个属性在管道控制分析的是哪个爬虫的 ...

  6. docker实战---初级<1>

    第1章 docker容器 1.1 什么是容器 容器就是在隔离的环境运行的一个进程,如果进程停止,容器就会销毁.隔离的环境拥有自己的文件系统,ip地址,主机名等 1.2 容器与虚拟化的区别 linux容 ...

  7. 通过js或jq增加的代码,点击事件或其他一些事件不起作用时

    通过js或jq增加的代码,点击事件或其他一些事件不起作用时,可使用 $(document).on("click",".noshow",function() { ...

  8. css基础重点内容总结

    一.目录引入 ./同级(当前) ../上级目录  ../../上上级目录 二.标签种类: 1.块级标签(block):独占一行,宽高可设: 2.行内块标签(inline-block):不独占一行,宽高 ...

  9. 记录ok6410 jlink 命令行调试uboot

    1\启动ok6410 进入uboot命令行 2\启动JLinkGDBServer -device ARM11 3\arm-none-eabi-gdb u-boot 初始化脚本 # Connect to ...

  10. 第一个Python窗口

    import tkinter def my_window(w, h): ws = root1.winfo_screenwidth(); hs = root1.winfo_screenheight(); ...