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(原型)属性,这个属性是一个指针,指向一个对象, ...
随机推荐
- 搭建MHA测试
搭建MHA: 手工切换: masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_maste ...
- vue中loding
<template> <div class="mf-loading-container" v-show="ifShow"> <im ...
- 创建存储过程 in,out,inout
in: 输入参数,存储过程如果修改了参数值,那么不能被返回. out:输出参数,存储过程中修改了参数值,可以被返回.inout:输入参数,存储过程如果修改了参数值,可以被返回 注意参数格式: in ...
- 出现error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
查看自己python的版本,然后下载自己版本Python的devel,比如python3.6.8就是 sudo apt-get install python3.6-dev
- python类之魔法方法
python类之魔法方法: class A(object): def __init__(self,x): self.x = x def __neg__(self): print('-v') def _ ...
- IconFont --阿里巴巴矢量库
超多的图标网站,可自己设置颜色,然后下载. IconFont --阿里巴巴矢量库
- js左右大小变化
点左边左边变大.点右边右边大左边小 <style type="text/css"> *{ margin:0px auto; padding:0px; } #wai{ w ...
- python headers missing
系统环境 win7 64 bit,cygwin,Gvim8.1 问题 Gvim通过插件管理器Vundle下载好了YouCompleteMe插件的全部文件. 利用cygwin 进入在YouComplet ...
- pygame 游戏舞台搭建典型应用
#两个文件要放在同一目录中,包括图片 一.搭建游戏舞台主程序 #!/usr/bin/env python3#_*_coding:utf-8_*_ author ==$ VACyp import sys ...
- Running ROS on Windows 10
1.在Windows10下安装ROS.需要开启WSL.参考 2.修改ubuntu国内源,可以提高安装包下载更新速度. (1)原文件备份:sudo cp /etc/apt/sources.list /e ...