JavaScript--原型链的深入

原型深入
函数本身也会有一些自己的属性
  • length:0 形参的个数
  • name :“Fn” 函数名
  • prototype:类的原型,在原型上定义的方法都是在当前Fn这个类实例的公有方法
  • _ _proto _ _:把函数当做一个普通的对象,指向Function这个类的原型
函数在整个JS中是最复杂也是最重要的知识:
一个函数存在了多面性:
  • “普通函数”:它本身就是一个普通的函数,执行的时候形成私有的作用域(闭包),形参赋值,预解释,代码执行,执行完成后栈内存销毁/不销毁
  • “类”:它有自己的实例,也有一个prototype属性是自己的原型,它的实例都可以指向自己的原型
  • “普通对象”:和var obj={ }中的obj一样,就是一个普通的对象,他作为对象可以有一些自己的私有属性,也可以通过 _ _proto _ _找到Function.prototype
call方法的深入
var obj = {name :'zhufeng'};
function fn(){
console.log(this);
}
fn();
//obj.fn(); 报错
fn.call(obj);
call方法的作用
首先我们让原型上的call方法执行,在执行call方法的时候,我们让fn方法中的this变为第一个参数值obj;然后再把fn这个函数执行。
面试题
function fn1(){console.log(1);}
function fn2(){console.log(2);}
fn1.call(fn2); //-> 1
fn1.call.call(fn2); //-> 2
首先fn1通过原型链机制找到Function.prototype上的call方法,并且让call方法执行, 此时call方法中的this就是我们要操作的fn1;在call方法代码执行的过程中首先让fn1中的“this关键字”变为fn2,然后再让fn1这个方法执行!
fn1.call.call(fn2); 解题思路:
function zhufeng(context){
1、先让this变成context
2,再让这个this方法执行
fn();//这是call的方法
}
Function.prototype.call = zhufeng;
fn1.call.call(fn2);
1、fn1.call是->zhufeng
2、zhufeng.call(fn2) ->先让call方法执行,call中的this是珠峰,让珠峰中的this变为fn2,再让珠峰执行
call、apply和bind的区别
apply和call方法的作用是一模一样的都是用来改变方法的this关键字并且把方法执行;而且在严格模式下和非严格模式下对于第一个参数是null/undefined的规律也是一模一样的
var obj = {name:"珠峰培训"};
function fn(num1,num2){
console.log(num1+num2);
console.log(this);
}
fn.call(obj,100,200);
fn.apply(obj,[100,200]);
fn.bind(obj,100,200);//->object {name:"珠峰培训"};
//->只是改变fn中的this为obj,并且给fn传递两个参数1,2;但是并没有把fn这个函数执行
var tempFn = fn.bind(obj,100,200);
tempFn();//执行bind会有一个返回值,这个返回值tempFn就是我们把fn你的this改变后的那个结果
(预处理)
call在执行的时候,call的第一个参数是用来改变this的,而从第二个参数开始都是传给调用call的函数的
'use strict';严格模式解析代码
* 严格模式: call执行的时候和非严格模式不同
* 没有参数:undefined
* null:null
* undefined:undefined
* 非严格模式都是window
* 在函数体内的arguments不随着参数变化而变化
* this问题:严格模式自执行函数中的thisundefined,如果没有执行主体 this也是undefined。非严格模式下都是window
this总结
THIS是谁和函数在哪执行的以及在哪定义的都没有任何的关系 (你以为 你以为的 就是你以为的)
在JS的非严格模式下
1、自执行函数中的THIS永远是window
->自执行函数:定义完成一个函数就立马执行了
(function(){})();
+function(){}();
!function(){}();
~function(){}();
2、给元素的某一个行为绑定一个方法,当行为触发的时候,执行对应的方法,此时方法中的THIS是“当前元素本身”
curEle.οnclick=function(){this->curEle};
3、当方法执行的时候,方法中的THIS是谁,就看方法名前面是否有”.”,有的话,”.”前面是谁THIS就是谁,没有的话THIS就是window
4、在构造函数模式中,方法体中的this.xx=xx中的this是当前类的一个实例
5、使用call/apply/bind来强制改变一个方法中的THIS指向
fn.call(); //this->window
fn.call(null); //this->window
fn.call(undefined); //this->window
在JS严格模式下 “use strict”
->自执行函数中的THIS是undefined
->使用call或者apply改变THIS和非严格模式有一些区别
fn.call(); //this->undefined
fn.call(null); //this->null
fn.call(undefined); //this->undefined
"use strict";
function fn() {
console.log(this);
}
fn();//this->undefined
window.fn();//this->window
->两者模式下的区别:非严格模式下所有没有具体写上执行主体的,都默许THIS是window,但是严格模式下,没有写的话,this就是undefined
sort的深入研究
var ary = [76,23,24,56,34,59,83];
ary.sort(function(a,b){
//a->每一次执行匿名函数的时候,找到的数组中的当前项
//b->当前项的后一项
return a-b; //升序 如果a>b ,返回的值大于0,a和b调换位置
return b-a; //降序 如果b>a 返回的值大于0,a和b调换位置
//return的值大于0,就两个数交换位置,若小于0,则为止不变;
});
二维数组的排序
var ary = [
{name : '田喜',age : 29},
{name : '珠峰',age : 30},
{name : '刘杰',age : 28}
];
ary.sort(function (a,b){
return a.name.localeCompare(b.name); //用汉字排序也换成了拼音
});
console.log(ary);//按照首字母的顺序排序
ary.sort(function (a,b){
return a.age-b.age; //按照年龄从小到大排序 -> (a.age - b.age)*-1 从大到小
});
console.log(ary);
回调函数:把一个方法A当做参数值传递给另一个函数B,然后在B执行的过程中,我们随时根据需求让A方法执行
获取数组中的最大值和最小值
var ary = [76,23,24,56,34,59,83];
//普通做法
ary.sort(function(a,b){
return a-b;
});
var min = ary[0];
var max = ary[ary.length-1];
console.log(min,max);
//假设法:假设当前数组中的第一个值是最大值,然后拿这个值跟后面的值逐一进行比较,如果后面后一个值比假设的还要大,说明假设错误,就把假设值替换掉。。->和自定义属性一样,都是常用的编程思想
var ary = [76,23,24,56,34,59,83];
var max = ary[0],min = ary[0];
for(var i=1;i<ary.length;i++){
var cur = ary[i];
cur>max?max=cur:null;
cur<min?min=cur:null;
}
console.log(min,max);
//使用Math中的max和min方法
var ary = [76,23,24,56,34,59,83];
var max = Math.max.apply(null,ary);
var min = Math.min .apply(null,ary);
求平均数
去掉最高分和最低分,然后求平均
function avgFn(){
var ary = Array.prototype.slice.call(arguments);
ary.sort(function(a,b){
return a-b;
});
[].shift.call(arguments);
[].pop.call(arguments);
return (eval([].join('+'))/ary.length).toFiexed(2);// ->保留两位小数
}
var res = avgFn(9,2,10,4,6,8,7,5);
console.log(res);
解题思路
  • 需要把这arguments这个类数组转化为数组
  • 因此我们可以自己克隆一个数组
  • slice这个方法在执行的过程中就是相当于把slice这个函数中的this就是调用slice的实例,如果把这里的this被改变成argumets。这样arguments就可以借用slice了
在IE6~8浏览器中,不支持借用数组的slice实现将元素集合(节点集合)的类数组转换成数组->报错
但是对于arguments借用数组的方法是没有兼容性问题的
浏览器的异常信息捕获
有时候既想捕获到错误的信息,又不想让下面的代码执行:
try {
console.log(num);
}catch (e){
//console.log(e.message); ->可以得到错误的信息
//手动抛出一条错误的信息,终止下面的代码执行
throw new Error('当前网络繁忙,请稍后再操作');
}
console.log('OK');

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值