关于this的东西
this是执行上下的最好体现,其实这里不会讲具体的东西,只是一点点的回顾。在整个JavaScript中,有哪些API或关键字是会和this的指向和绑定有问题的。来我们理一下:
- call / apply :其实这两个API是确定this的东西,也是可以指定this的API,第一个参数就是this的值。这两个区别的主要在于第二个参数的区别,call的是以一个一个的参数传递的,而apply的第二个参数就是以数组的方式传递参数。
- bind:这个API就是也是第一个参数绑定函数的this值,返回一个新的函数再次调用。其实这个函数还有一个特性就是this指向的值不能修改的,因为返回的新的函数,这个函数里面是执行了原本的函数。所以有这么一个问题看链接,最后的call方法只是改变了包裹函数的this值却没有改变bind的函数最终返回的结果。这个真的要看英文文档和源码才能知道的一点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| Function.prototype.bind = function(){ var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function(){ return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); }; }; if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP ? this : oThis || this, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; }
|
- new:其实很多情况下,会忘记这个关键字的存在,因为觉得理所当然了,而这个关键字的作用就是能将函数的this指向实例化出来的对象
- 特殊情况下,在ES6 语法中箭头函数也是绑定了this,其指向的就是最外层的词法作用域,在这里就不展开这个知识点。
有关于继承的知识点
今早的有一个面试,问道我对OOP编程的看法。哈哈,其实还是一个编程的思潮而已,可谈到相面对象的主要会引导一个问题就是继承。而继承这个东西在JavaScript中,并没有像Java的当中那样extends,可有些人了解到了ES6的东西,里面确实有这个语法糖可以继承一些组件。但涉及到原生的JavaScript的时候,这一点的引出的原型链这个知识点最为重要。
那我们来想一个需求,我手上有一个human
的Fn,看下面:
1 2 3 4 5 6 7
| function human(name, age){ this.name = name this.age = age } human.prototype.sayName = function(){ console.log(this.name) }
|
那我现在想要创建一个student
的Fn,去继承human
的类,就有了如下的:
1 2 3 4 5
| ... function student(name,age, college){ human.call(this,name,age) this.college = college }
|
其实以上是可以的了,但是有一个问题呀!我们这时候不能调用human.sayName
,这时候我们就要想到了原型链的东西,其实想想也知道很多的公共函数都是放在对象的原型链上的,那我们就将student的原型指向humane的原型不就好了吗?所以我们这样做:
1
| student.prototype = human.prototype
|
其实这样大致也是可以的,只不过这里出现了一个问题,我想给student
的原型链上的加上一些东西,其实也就是加在了human
的原型上了,这样使得human
函数变得不是那么pure
,对于之后使用human
的拓展不是很好,所以我们可以使用新的函数来指向human的原型,于是我们这样做:
1 2 3
| var Fn = function (){} Fn.prototype = human.prototype student.prototype = new Fn()
|
这样我们可以在原型链上使用了human.sayName
方法,而我们在student
原型上加方法也不会改到了human
的方法。其实这样的方法也是很复杂的,想想整体的思路,就是指向human的对象吧,那我们想想能不能拷贝一份这样的对象,噢!想到了,Object.create()
看这里,所以我们改写了代码:
1
| student.prototype = Object.create(human.prototype)
|
以上就是笔者对继承的了解。
排序算法
名词解释:
n:数据规模
k:“桶”的个数
In-place:占用常数内存,不占用额外内存
Out-place:占用额外内存
稳定性:排序后2个相等键值的顺序和排序之前它们的顺序相同
冒泡排序:「教官双手算法:较高的往后排」
两个循环体完成整个排序,第一个循环体主要引导循环的次数,第二个循环体的作用是当前循环中的大小比较。说白了整个逻辑是都要循环,次数是一次比一次少一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var arr = [4,5,1,2,3,7,6] function bubbleSort(arr) { var len = arr.length for(var i = 0; i<len; i++){ for(var j = 0; j<len-1-i; j++){ if(arr[j]>arr[j+1]){ swap(arr,j+1,j) } } } return arr } function swap(arr,i,j){ var temp = arr[i] arr[i] = arr[j] arr[j] = temp; }
|