谈谈我认识的js原型
众所周知,JavaScript中是没有传统类的概念的,js通过原型链的方式实现继承。原型是js学习中的一大重点知识,在ES6出来之前,因为js不像php、java一样拥有类的写法,所以继承方式也就不像php、java一样通过关键字extends实现子类继承父类的方式,但是js有它独特的实现继承的方式,这种方式有:prototype、原型冒充、复制继承。
1、prototype
js中每个函数就是一个对象,每个对象都有自己的prototype属性,通过这个属性,可以指定某一类对象的原型
function Person(name,age,sex){
this.name = name || " ", //设置默认值,如果传入实参,this.name的值就等于实参的值,否则this.name的值默认为 " "
this.age = age || 24,
this.sex = "男" || sex,
this.say = function (){
console.log("我会说话");
},
this.smile = function(){
console.log("笑");
},
this.walk = function(){
console.log("走路");
}
};
function Monkey(){
this.type = "monkey";
};
var oop = new Person();
Monkey.prototype = oop;
var oom = new Monkey();
//执行oom.say()输出 我会说话
oom.say();
oom对象并没有say()方法,为什么程序没有保存而且控制台还输出了 “我会说话”。因为oom对象的构造函数的prototype属性指向oop对象,表明由Monkey构造函数创建出来的一类对象,他们都具有共同的原型:oop对象。所以oom对象调用say()方法中,程序会默认先在oom对象中查找,如果没有找到这个属性,程序会沿着原型链往上寻找该属性。
需要注意的是,js中new 构造函数()这个过程发生了如下的操作:
a、创建空对象 { };
b、this指向空对象{ };
c、执行构造函数的函数体。
在过程c中,如果你熟悉js的为对象添加属性的方式(对象名 . 属性),你会发现,过程c其实就是给这个空对象添加属性和方法的过程。
构造函数名 。prototype = 对象 ,这个对象也可以是自定义的对象,在这个对象中定义了需要用到的方法和值。如下例子所示:
function op(){
a = 3;
};
var obj = {
para : 1,
say : function(){console.log("obj");}
};
//指定构造函数op的原型是obj对象;
op.prototype = obj;
//由构造函数op创建的oop对象能够调用对象obj中的方法
var oop = new op();
oop.say();
2、原型冒充
原型冒充的原理是通过call()与apply()函数改变当前对象的this的执行上下文。这话说的有点抽象,下面直接用例子解释:
//函数
function increase(a , b){
return a+b;
}; function reduce(a , b){
return a-b;
}
increase . call(reduce,1,2); //输出3 reduce . call(increase,1,2); //输出-1 解释 :对象A . call(对象B , 参数1 , 参数2 , ......参数n)中执行了这样的操作: a、修改对象A的this的指向,使其暂时指向对象B,参数1与参数2是传入对象B的实参。 b、执行调用call()方法的对象。 所以increase . call(reduce,1,2); 这一句相当于increase中this指向reduce,然后执行increase(1,2),所以最终结果输出3。 //对象 function person(name){
this.name = name;
this.say = function(){
console.log(this.name);
}
};
var op = new person("张三");
op.say(); function lisi(name){
this.name = name;
};
var ls = new lisi("李四");
op.say.call(ls);//this指向ls :op.say(){ console.log(ls.name) },执行op.say()方法,输出 李四
op.say.call(ls)这句代码先是将say()函数体内的this指向ls,然后执行say()方法。op.say();这一步在正常情况下输出的结果应该是"张三",但是为什么却是“李四”了呢?原因是op.say.call(ls)这句代码将say()函数在程序解析到这句代码的位置时,this暂时指向对象ls,所以在op对象的say()体内的输出语句console.log(this.name)实际上是console.log(ls.name);
3、复制继承
复制继承的原理是,将对象以参数的形式传递到构造函数中,在构造函数中通过对象属性的方式(Objname . propertyname或者Objname[propername])访问盖对象的属性值,将值赋予当前对象的属性。
function Person(){
this.name = "张三";
this.age = 24;
this.sex = "男"
}
function children(per){
this.name = per.name;
this.age = per.age;
this.sex = per.sex;
}
var op = new Person();
//向children构造函数中传入op对象,在children函数内完成值的复制
var chi = new children(op);
console.log(chi.age);
以上均是js原型继承的实现方式,在js这个海洋中,因为知识有限,所以博客还存在很多不足之处,希望更够跟大家多多交流学习。
谈谈我认识的js原型的更多相关文章
- JS原型链
JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...
- 深入分析JS原型链以及为什么不能在原型链上使用对象
在刚刚接触JS原型链的时候都会接触到一个熟悉的名词:prototype:如果你曾经深入过prototype,你会接触到另一个名词:__proto__(注意:两边各有两条下划线,不是一条).以下将会围绕 ...
- 【09-23】js原型继承学习笔记
js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...
- js原型
1.js基本类型和对象类型 js的简单类型包括数字(其中NaN为数字类型).字符串(类似'A'为字符,js没字符类型).布尔值.null值和undefined值.其他所有的值都是对象.数字.字符串和布 ...
- js原型链与继承(初体验)
js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询 ...
- JS 原型链图形详解
JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语 ...
- js原型解析
我们都知道javascript因为具有了继承以及变量等等一系列的特性之后才被人们认为具有一门编程语言的资格,在后续的不断发展中,js在原生的基础上扩展了基于jquery等等的库,甚至衍生了像node. ...
- 深入理解JS原型链与继承
我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天 ...
- 学习zepto.js(原型方法)
学习zepto.js(原型方法)[1] 转载 新的一周,新的开始,今天来学习一下zepto里边的原型方法,就是通过$.进行调用的方法,也是可以通过$.fn进行扩展的方法: $.camelCase(): ...
随机推荐
- 微信退款通知,退款回调数据解密.SHA256签名AEAD_AES_256_GCM解密
$xmlResult = file_get_contents("php://input");//获取微信的数据$result = $this->xmlToArray($xml ...
- 华为三层交换机5700 DHCP配置
交换机配置DHCP配置 1,交换机作DHCP Server『配置环境参数』1. PC1.PC2的网卡均采用动态获取IP地址的方式2. PC1连接到交换机的以太网端口0/1,属于VLAN10:PC2连接 ...
- LGP4916题解
第一眼,Burnside 直接丢上去啊. 设 \(f(n,m)\) 是有 \(n-m\) 个白色珠子和 \(m\) 个白色珠子的满足题意的环的个数,容易得到答案是: \[\sum_{d|n,d|m}f ...
- .NET 7 预览版2 的亮点之 NativeAOT 正式合并入 .NET 主线
.NET 中备受追捧和期待已久的功能NativeAOT终于出现在本周的.NET 7 预览版2中,该项目的工作仍在继续,该版本将 NativeAOT 从实验性的 dotnet/runtimelab re ...
- hadoop-SSH免密登录配置
一:配置基础环境 一.修改主机名 修改 master 机器主机名 [root@server ~]# hostnamectl set-hostname master-wzg [root@server ~ ...
- WPF 可视化树的用途
1.可视化树的主要用途: 1.可以使用样式改变可视化树中的一个元素.可以使用Style.TargetType属性选择希望修改 的特定元素.甚至当控件属性发生变化时,可以使用触发器自动完成更改. 2.可 ...
- mac电脑sublime text3安装pretty json插件
因http://packagecontrol.io/地址被墙无法实现自动安装,导致sublime Text3安装插件非常麻烦,总是出现There Are No Packages Available F ...
- 5分钟了解Redis的内部实现快速列表(quicklist)
快速列表简介 在Redis3 .2版本之前,存储列表(list)数据结构使用的是压缩列表(ziplist)和链表(linkedlist),当列表元素个数比较少并且每个元素占用空间比较小的时候,使用压缩 ...
- mq消息堆积处理
1.大量消息在mq里积压 场景:几千万条数据在MQ里积压了七八个小时,从下午4点多,积压到了晚上很晚,10点多,11点多.线上故障了,这个时候要不然就是修复consumer的问题,让他恢复消费速度,然 ...
- spinlock 设计的初衷,当只有单核时是否还需要锁
自旋锁,的设计初衷是什么,是为了解决什么问题.如果只有一个cpu,并且是单核,那是否还需要用到自旋锁.