js原型和原型链理解到面向对象
一、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原型和原型链理解到面向对象的更多相关文章
- js小记:对象、原型及原型链、面向对象编程
一.js对象 1.js对象 js对象是一种复合数据类型,它可以把多个(不同类型的)数据集中在一个变量中,并且给每个数据起名字. 2.对象与数组 对象的每个数据有对应的名字(属性名),我们通过叫名字访问 ...
- JS基础-该如何理解原型、原型链?
JS的原型.原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对 ...
- js原型链理解(2)--原型链继承
1.原型链继承 2.constructor stealing(构造借用) 3.组合继承 js中的原型链继承,运用的js原型链中的__proto__. function Super(){ this.se ...
- 前端【JS】,深入理解原型和原型链
对于原型和原型链,相信有很多伙伴都说的上来一些,但有具体讲不清楚.但面试的时候又经常会碰到面试官的死亡的追问,我们慢慢来梳理这方面的知识! 要理解原型和原型链的关系,我们首先需要了解几个概念:1.什么 ...
- Js中关于构造函数,原型,原型链深入理解
在 ES6之前,在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但 ...
- JS原型、原型链深入理解
原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 一.初识原 ...
- 理解js中的原型链
对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 关于原型 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承 ...
- JS原型与原型链继承的理解
一.原型 先从构造函数开始吧! 构造函数是什么?构造函数与其他函数唯一的区别在于调用方式不同.任何函数只要通过new来调用就可以作为构造函数,它是用来创建特定类型的对象. 下面定义一个构造函数 Fem ...
- 理解js中的原型,原型对象,原型链
目录 理解原型 理解原型对象 实例属性与原型属性的关系 更简单的原型语法 原型的动态性 原型链 理解原型 我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象, ...
随机推荐
- javascript的ES6学习总结(第一部分)
ES6(ESNext学习总结——第一部分) ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版. ECMA每年6月份,发布一个版本 201 ...
- 【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 ...
- 安卓微信端打开H5页面背景图被键盘挤压移动位置解决
问题:在微信端(安卓浏览器也如此)打开的H5登录页面中,点击输入信息,弹出软键盘会挤压背景图片. 本来的body宽高设置body{width:100%,height:100%},不起作用,这样写就会导 ...
- 解决IE浏览器把application/json响应视为文件并尝试下载
下面我的解决方案是针对.net MVC的,其他的解决方案也类似,就是把响应的mimeType换成IE浏览器已经拥有的.如application/json换成text/plain #region 退出登 ...
- Scrapy详解
一.爬虫生态框架 在管道传数据只能传字典和items类型. 将 上一return语句注释则会报错 如: 如上图,爬虫文件中有一个name属性,如果多个爬虫可以通过这个属性在管道控制分析的是哪个爬虫的 ...
- docker实战---初级<1>
第1章 docker容器 1.1 什么是容器 容器就是在隔离的环境运行的一个进程,如果进程停止,容器就会销毁.隔离的环境拥有自己的文件系统,ip地址,主机名等 1.2 容器与虚拟化的区别 linux容 ...
- 通过js或jq增加的代码,点击事件或其他一些事件不起作用时
通过js或jq增加的代码,点击事件或其他一些事件不起作用时,可使用 $(document).on("click",".noshow",function() { ...
- css基础重点内容总结
一.目录引入 ./同级(当前) ../上级目录 ../../上上级目录 二.标签种类: 1.块级标签(block):独占一行,宽高可设: 2.行内块标签(inline-block):不独占一行,宽高 ...
- 记录ok6410 jlink 命令行调试uboot
1\启动ok6410 进入uboot命令行 2\启动JLinkGDBServer -device ARM11 3\arm-none-eabi-gdb u-boot 初始化脚本 # Connect to ...
- 第一个Python窗口
import tkinter def my_window(w, h): ws = root1.winfo_screenwidth(); hs = root1.winfo_screenheight(); ...