基于原生JS封装数组原型上的sort方法
基于原生JS封装数组原型上的sort方法
最近学习了数组的原型上内置方法的封装,加强了用原生JS封装方法的能力,也进一步理解数组方法封装的过程,实现的功能。虽然没有深入底层,了解源码。以下解法都是基于个人理解用纯原生JS实现的功能。如有不对的地方,可以评论告诉我哟
首先,我们先来看一下sort方法的作用、参数、以及方法的返回值,原有数组是否发生改变
sort方法主要用于数组的排序
参数分为两种:
- 一种:传的参数是函数、 (排序主要看函数的返回值)
- 另一种:传的不是函数、或者不传(只要传的不是函数就对原来排序过程不产生影响)
方法的返回值是原来数组排序后的数组
原来数组发生改变,是排序后的数组
其次,我们来看一下sort方法要处理的各种情况之间的比较
情况1:无参实现对字符串数组的排序
情况2:无参实现对number类型的数组进行排序
情况3:无参实现对字符串、number等混合类型的数组的排序
情况4:带参实现对number类型的数值数据排序
情况5:带参sort()对简单对象List的自定义属性排序
情况6:带参实现对字符串、number混合类型的数组的排序
sort方法对参数的处理:
情况1:如果参数不是函数,则不影响原来排序过程
情况2:如果参数是函数,则根据回调函数中的返回值进行排序。如果返回值大于0,则交换位置;如果返回值小于0,则不交换位置
如果返回值不是一个数字,则不交换位置
基于以上情况的讨论,sort方法实现的核心原理如下:
核心原理:不带参(以及带的参数不是函数)的情况下:默认升序排列
不带参的情况下,直接转字符串,逐个比较ASCII码的值
只要有一个是对象{}就不交换
带参数为函数的情况下:
根据函数的返回值进行比较;如果函数返回值大于0;则交换位置
实现代码如下:
Array.prototype.mySort = function(fn){
if(Object.prototype.toString.call(fn)==='[object Function]'){
//如果传进来参数的是函数
for(var i = 0;i<this.length-1;i++){
//遍历数组,将前后两项作为实参传给fn
if(fn.call(this,this[i],this[i+1])>0){
//如果fn执行之后的返回值大于0.就调用swap方法交换位置
var a = this[i],b=this[i+1];
this[i] = swap(a,b).a;
this[i+1] = swap(a,b).b;
//交换之后,如果当前项不是第一项,则当前项(索引为i的项)继续跟前面的项进行比较
if(i>0){
for(var j = i-1;j>=0;j--){
if(fn.call(this,this[j],this[j+1])>0){
var a = this[j],b=this[j+1];
this[j] = swap(a,b).a;
this[j+1] = swap(a,b).b;
}
}
}
}
}
}else{
//如果不是函数,则按正常排序
//遍历数组,将前后两项进行比较
for(var i = 0;i<this.length-1;i++){
var cur = this[i];//当前项
var next = this[i+1];//下一项
if(comASCII(cur,next)){
//当返回true的时候交换,并且交换完成之后,当前项继续往前比较
this[i] = swap(cur,next).a;
this[i+1] = swap(cur,next).b;
//当前项继续向前比较
if(i>0){
for(var k = i-1;k>=0;k--){
var cur = this[k];
var next = this[k+1];
if(comASCII(cur,next)){
this[k] = swap(cur,next).a;
this[k+1] = swap(cur,next).b;
}
}
}
}
}
}
//封装一个交换位置的函数
function swap(a,b){
return {
a:b,
b:a
}
}
//如果不传参的情况下比较ASCII码
function comASCII(cur,next){
//全部转换为字符串、逐项比较ASCII码
cur = cur.toString();
next = next.toString();
//取长度最大值
var len = cur.length>next.length?next.length:cur.length;
//当前后两项都不是不是{}类型的数据时,进行比较
if(cur!=='[object Object]'&&next!=='[object Object]'){
for(var j = 0;j<len;j++){
if(!isNaN(cur.charCodeAt(j))&&!isNaN(next.charCodeAt(j))){
//如果二者的ASCII码都是有效数字
if(cur.charCodeAt(j)>next.charCodeAt(j)){
//如果前一项比后一项当前的ASCII码大,则返回true,交换位置
return true;
}else if(cur.charCodeAt(j)==next.charCodeAt(j)){
//如果相等直接进入下一轮循环
continue;
}else{
//前项比后项小,直接返回false
return false;
}
}
}
if(!isNaN(cur.charCodeAt(len))&&isNaN(next.charCodeAt(len))&&(cur.charCodeAt(len-1)==next.charCodeAt(len-1))){
//比较完之后,如果前一项ASCII还是有效数字,说明前项比后项大,交换
return true;
}
}
//如果上述条件不满足,则不交换
return false;
}
//返回当前数组
return this;
};
实验结果
无参(参数非函数)对纯数字数组的排序

带参对纯数字数组的排序(升序)

带参对纯数字数组的排序(降序)

无参(参数非函数)对纯字母字符串数组的排序

带参(参数是函数)对纯字母字符串数组的排序(升序)

带参(参数是函数)对纯字母字符串数组的排序(降序)

无参(参数非函数)对纯字母字符串、数字字母组合字符串、纯数字字符串组合的排序

带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(升序)

带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(降序)

无参(参数非函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果

带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(升序)

带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(降序)

无参(参数非函数)对数组、纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的排序

带参(参数是函数)对数组、纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的排序(升序)

带参(参数是函数)对数组、纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的排序(降序)

带参(参数是函数)对纯数组的排序(升序)

带参(参数是函数)对纯数组的排序(降序)

带参(参数是函数)对纯对象的排序(升序)

带参(参数是函数)对纯对象的排序(降序)

基于原生JS封装数组原型上的sort方法的更多相关文章
- 用jQuery基于原生js封装的轮播
我发现轮播在很多网站里面都用到过,一个绚丽的轮播可以为网页增色不少,最近闲来无事,也用原生js封装了一个轮播,可能不像网上的插件那么炫,但是也有用心去做.主要用了闭包的思想.需要传递的参数有:图片地址 ...
- 基于原生js的图片延迟加载
当页面图片比较多的时候,我们通常会做一个延迟加载,避免页面打开时一下子的请求数太多,加载过慢影响用户体验. 如果项目用了jquery框架,则可以直接用 jquery.lazyload.可在jquery ...
- 基于原生js的返回顶部组件,兼容主流浏览器
基于原生js的返回顶部插件,兼容IE8及以上.FF.chrome等主流浏览器. js文件中封装了getScrollTop()和changeScrollTop()函数分别用于获取滚动条滚动的高度和修改滚 ...
- 原生JS封装创建多级菜单函数
手写一个使用原生JS封装的多级菜单的函数,满足以下几点需求. 子类层级不确定,可根据数据自动生成多级菜单. 操作便捷,只需传入一个HTML标签. 缺点: 需要满足特定的数据结构 废话不多说,展示代码. ...
- 用原生js封装轮播图
原生js封装轮播图 对于初学js的同学来说,轮播图还是一个难点,尤其是原生js封装轮播图代码,下面是我之前做的一个轮播图项目中封装好的一些代码,有需要的同学可以看一下,有什么不懂的可以看注释,注释看不 ...
- 使用原生JS封装一个动画函数
最近一直在忙项目,很少有时间回顾之前的知识,今天刚好要做一个轮播,因为对兼容性有一定的要求,使用了各种插件和库中的轮播,效果都不是很理想,一怒之下,使用原生JS封装了一个轮播组件,其中重要的功能就是一 ...
- 原生JS封装Ajax插件(同域&&jsonp跨域)
抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...
- 原生JS封装简单动画效果
原生JS封装简单动画效果 一致使用各种插件,有时候对原生JS陌生了起来,所以决定封装一个简单动画效果,熟悉JS原生代码 function animate(obj, target,num){ if(ob ...
- 原生Js封装的弹出框-弹出窗口-页面居中-多状态可选
原生Js封装的弹出框-弹出窗口-页面居中-多状态可选 实现了一下功能: 1.title可自定义 可拖拽 2.width height可以自定义 3.背景遮罩和透明度可以自定义 4.可以自己编辑弹出 ...
随机推荐
- 快速替换dll命名空间 z
Step1:使用ildasm将代码反编译成il中间语言. 名字存贮为你想要的名字. Step2:用记事本打开il文件全局替换命名空间. Step3:使用ilasm将il文件编译成dll 按下回车即可生 ...
- 网页入口ControlServlet分析
init() configureBsf(); //配置自定义bsf,即在bean script中注册ofbiz实现的脚本引擎 getRequestHandler(); //初始化request han ...
- 设计模式:代理(Proxy)模式
设计模式:代理(Proxy)模式 一.前言 代理模式或许我们都听说过,至少知道代理(Proxy)这个东西的,否则看这篇博客也没任何意义的.什么叫做代理,代理是代替服务器去接受请求者的请求的中间人 ...
- Android(java)学习笔记208:Android下的属性动画高级用法(Property Animation)
1. 大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是最常用的一些用法,这些用法足以覆盖我们平时大多情况下的动画需求了.但是,正如上篇文章当中所说到的,属性动画对补间动画 ...
- 解决weblogic错误:java.sql.SQLRecoverableException: IO Error: Broken pipe
首先说一下系统基础架构: 服务器:weblogic11g集群 数据库:oracle数据库Rac 出错信息: 1.java.sql.SQLRecoverableException: Closed Con ...
- [BJOI2018]治疗之雨
题目 我还没疯 发现如果我们将血量抽象成点,一轮操作抽象成图上的一条边,我们如果能求出每一条边的概率,我们就能搞一下这道题 假设我们求出了这个图\(E\),设\(dp_i\)表示从\(i\)点到达\( ...
- 常用的css选择器
1.最基本的 * * 选择所有元素. #id #firstname 选择 id="firstname" 的元素. .class .intro 选择 class="intr ...
- webstorm window找不到文件'chrome'
1.打开webstorm设置: File->Settings->Tools->Web Browsers->更改谷歌浏览器的Path(获取方式:谷歌浏览器的快捷键->右键- ...
- rnnlm学习
rnn-lm: 1.论文 2.公式推导 2.1 http://blog.csdn.net/a635661820/article/details/44462315 3. 工具 lstm-lm 1. 论文 ...
- MVC学习十:MVC 特性作用和MVC 验证
根据代码分析特性用处 [DisplayName("学员名")] [DataType(DataType.Text)] [StringLength(,ErrorMessage=&quo ...