这一篇文章主要是讲述一些有关js的小知识点。由于我也不是很精通哪一方面只能把本身知道的一点点写出来。取名大杂烩也是这意思吧,既然是道菜那么就来尝尝个人手艺吧。后端
第一道菜数组
1.首先,我想说一下事件绑定。 事件绑定咱们都知道有:on + 'type'
的事件绑定还有addEventListener
的事件绑定。浏览器
function bindEvent(obj, type, handle) {
if(window.addEventListener){
obj.addEventListener(type, handle, false);
}
if(window.attachEvent){ // IE
obj.attachEvent('on' + type, handle);
}
obj['on' + type] = handle;
}
复制代码
on + 'type'
其余的就是怎么绑定怎么解除。function delEvent(obj, type, handle) {
if(window.removeEventListener){
obj.removeEventListener(type, handle, false);
}
if(window.detachEvent){ // IE
obj.attachEvent('on' + type, handle);
}
obj['on' + type] = null;
}
复制代码
function handle(e){
let event = e || window.event; // IE
let target = e.target || e.srcElement;
}
复制代码
下一篇我会详细介绍DOM事件绑定和DOM事件等级。第二道菜bash
2.这个知识点咱们来讲一下继承。app
function Father(){
this.a = 1;
}
Father.prototype.show = function () {
console.log(this.a);
}
function Son(){
Father.call(this);
}
let son = new Son();
console.log(son.a);
console.log(son.show());
复制代码
function Father(){
this.a = 1;
}
Father.prototype.show = function () {
console.log(this.a);
}
function Son(){
Father.call(this);
}
Son.prototype = Father.prototype; //多了这一行
let son = new Son();
console.log(son.a);
console.log(son.show());
复制代码
function Father(){
this.a = 1;
}
Father.prototype.show = function () {
console.log(this.a);
}
function Son(){
Father.call(this);
}
function F(){}; //借用中间层来防止Son改变Father的原型
F.prototype = Father.prototype;
Son.prototype = new F();
Son.prototype.constructor = Son; //改变Son的constructor
let son = new Son();
console.log(son.a);
console.log(son.show());
console.log(son.constructor);
复制代码
function Father(){ this.a = 1; }
这个是否是构造函数?若是说是那你就错了,由于你思惟固定了。咱们都说构造函数开头首字母大写但那只是人为的规定并非语法。还有若是有人问你
this
是谁,你能够放肆的告诉他,你没调用我知道是谁啊。
new
只是一个操做符,任何函数都能经过new来执行,并不仅是构造函数,只不过咱们认为
new
以后的都是构造函数。
new
的时候发生了什么吗?咱们通常都说四步走
function myNew(){
let obj = {};
let Constructor = arguments[0];
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
}
let a = myNew(Son);
console.log(a);
复制代码
class Father {
constructor(){
this.a = 1;
}
show(){
console.log(this.a);
}
}
class Son extends Father {
constructor(){
super();
}
}
let son = new Son();
console.log(son.a);
console.log(son.show());
复制代码
class
这种实现方式只是一个‘语法糖’,当咱们用
typeof Son
的时候咱们发现他是一个
function
,其实它就是一个函数只不过更加语义化了,并且里面定义的方法实际上是定义在了它的原型上面,咱们输出一下
Father
看看。
第三道菜函数
3.咱们再来介绍一下call、bind、applyui
演示我以为应该不用了吧,由于我不是在写文档,那么咱们说一些什么呢,就说说怎么模拟实现吧。我这里用的是ES6的语法,我只是以为这样写比较简单但整体思路不变。 下面以这个为例:this
var a = 3;
var obj = {
a: 1
}
function show(g) {
console.log(this.a, g);
}
复制代码
Function.prototype.callh = function(context){
let args = [...arguments].slice(1); //首先获取到传递的参数
context.fn = this; // 获取当前的调用者,并添加一个方法
context.fn(...args); // 传入参数
delete context.fn; //删除新增的函数
}
show.callh(obj, 2);
复制代码
Function.prototype.applyh = function(context){
let args = arguments[1]; // 跟call同样,只不过apply传进来的是数组,因此arguments[1]指的是后面的参数
context.fn = this;
context.fn(...args);
delete context.fn;
show.applyh(obj, [2]);
}
复制代码
// 简易版
Function.prototype.bindh = function(context){
let args = [...arguments].slice(1);
let that = this;
return function (argument) { // bind返回一个函数
let args2 = [...arguments].slice(0);
that.call(context, ...args.concat(args2));
}
}
show.bindh(obj)(5);
复制代码
由于原型的缘由,咱们来改进一下。spa
Function.prototype.bindh = function(context){
let args = [...arguments].slice(1);
let that = this;
function bnd(){}
let fn = function (argument) {
let args2 = [...arguments].slice(0);
return that.call(this instanceof fn ? this : context, ...args.concat(args2));
}
bnd.prototype = this.prototype;
fn.prototype = new bnd();
return fn;
}
复制代码
这样就好了。prototype
第四道菜
4.再来说一讲this
我想到的差很少就这几种吧,你或许会发现实际上是按this绑定的优先级升序排序的。若是你看懂了bind的模拟实现也许会知道为何bind的优先级会高于call、apply。我以为弄清楚这些this应该不是多大的问题吧,来一段代码看看。
var a = 3;
var obj = {
a: 1,
fn(){
console.log(this.a);
}
+
}
function show() {
console.log(this.a);
}
show(); //3
obj.fn(); //1
show.call(obj); // 1
show.apply(obj); // 1
show.bind(obj)(); // 1
show.bind(window).call(obj); //3 bind优先级高,跟绑定顺序没区别
复制代码
但愿这些菜能知足您的胃口,希望也能给您填饱一些肚子。我之后还会继续努力提升本身的厨艺,但愿尝到这个菜的人都会喜欢。