在ecs内使用chrome完成了javascript学习

本文涉及的产品
云服务器 ECS,每月免费额度280元 3个月
云服务器ECS,u1 2核4GB 1个月
简介: 在ecs内使用chrome完成了javascript学习

函数高级

函数的定义的三种方式

  • 声明方式(匿名函数)
  • new Function()方式(不常用)
  • 使用call调用
  • 对象的方法
  • 构造函数
  • 绑定事件函数
  • 定时器函数
  • 立即执行函数

//函数的定义的三种方式

//定义方式

functionfn() {};

fn();

//声明方式(匿名函数)

varfunc=function() {};

func();

//new Function()方式(不常用)

varf=newFunction('a', 'b', 'console.log(a+b)'); //a,b 为形参 Function参数都为字符串格式,效率低

f(1, 2);

//所有的函数都是 Function 的实例(对象)

//函数也属于对象

console.log(fninstanceofObject);

console.log(fn.__proto__.constructor); //函数的原型对象的构造函数就是Function

//函数的调用方式

fn(); //常规调用方式

fn.call(); //使用call调用

//对象的方法

varo= {

   fnfn: function() {

       console.log('ddd');

   }

};

o.fnfn();

//构造函数

functionStar() {}

newStar();

//绑定事件函数

document.onclick=function() {};

//定时器函数

setInterval(function() {}, );

//立即执行函数

(function() {})();

函数的this指向

  • 普通函数
  • 对象方法
  • 绑定事件函数
  • 定时器函数
  • 立即执行函数

//普通函数

functionfn11() {

   console.log('普通函数的this'+this) //指向window

}

fn11();

//对象方法

varo= {

   fnfn: function() {

       console.log('对象方法this', this); //指向对象本身

   }

};

//构造函数 this 指向实例对象 指向kano这个实例对象

functionStar() {}

Star.prototype.sing=function() {

   console.log(this);

}; //原型对象的this指向的也是kano这个实例对象

varkano=newStar();

kano.sing();

//绑定事件函数 this指向的是函数的调用者 document这个对象

document.onclick=function() {

   console.log('绑定事件函数的this'+this);

};

//定时器函数

setTimeout(function() {

   console.log("定时器的this"+this); //还是指向window

}, 1000);

//立即执行函数

(function() {

   console.log('立即执行函数this'+this) //也是指向window

})()

总结:this指向,是当我们调用函数的时候决定的,调用方式的不同决定了this指向不同 ,一般是指向我们的调用者

调用方式 this指向
普通函数的调用 window
构造函数的调用 实例对象,原型对象里面的方法也指向实例对象
对象方法调用 该方法所属对象
事件绑定方法 绑定事件对象
定时器函数 window
立即执行函数 window

改变函数内部的指向

  1. call方法 调用一个对象,简单理解为调用函数的方式,但是它可以改变这个函数的this指向
  2. apply方法
  3. bind方法
语法

function.call(thisArg, arg1, arg2, ...)

func.apply(thisArg, [argsArray])

func.bind(thisArg, arg1, arg2, arg3.....)

  • thisArg:在fun函数运行时指定的this值
  • argx :传递的其他参数
示例

bind方法

//call方法 调用一个对象,简单理解为调用函数的方式,但是它可以改变这个函数的this指向

varo= {

   name: 'kano'

}

functionfn(a, b) {

   console.log(this)

   console.log(a+b);

}

fn.call(o, 1, 2);

//call的主要作用可以实现继承

functionFather(name, age, sex) {

   this.name=name;

   this.age=age;

   this.sex=sex;

}

functionSon(name, age, sex) {

   Father.call(this, name, age, sex)

}

varson=newSon("kano", 18, '女');

console.log(son);

apply方法

//apply方法

varo1= {

   name: 'kano'

};

functionfn(arr) {

   console.log(this);

   console.log(arr);

}

fn.apply(o1, ['我是字符串']);

//1. 也是调用函数 第二个可以改函数内部的this指向

//2. 但是他的参数必须是数组或者伪数组

//下面的方法使用 apply 方法寻找一个数值数组中的最大元素。 Math.max.apply([1, 2, 3]) 等价于 Math.max(1, 2, 3), 但是你可以使用 Math.max.apply 作用于任意长度的数组上。

varmax=Math.max.apply(null, [1, 2, 2, 1, 2, 1, 4, 23, 14, 32, 15, 43, 512, 43, 16, 32, 6, 32, 5, 43, 25]); //这里不需要传递对象进去就可以写null,但是这里推荐写Math,具体原因参考后面的严格模式

//最小值同理

//注意:虽然apply传递的是一个数组的形式,但是他进入函数时候会把数组依次转换成我们想要的格式

console.log("最大值是:"+max);

//高效率的push方法

vararr1= [1, 2, 3, 4, 5];

vararr2= [6, 7, 8, 9, 10];

arr1.push.apply(arr1, arr2);

console.info(arr1);

bind方法

//bind方法

//bind方法不会调用函数,但是能改变函数内部的this指向

//fun.bind(thisArg, arg1, arg2, arg3.....)

//thisArg:在fun函数运行时指定的this值

//argx :传递的其他参数

//返回由指定的this和初始化参数改造的 原函数拷贝

//就相当于我用自己的参数绑定了那个函数,由于是先拷贝后改变,所以原函数其实是不变的

functionfn2(a, b) {

   console.log("bind:"+this+ (a+b));

}

varfncp=fn2.bind(o, 2, 3);

console.log(fncp);

fncp(1, 2); //bind:[object Object]5 //因为bind中使用参数之后就变成了被预置入绑定函数的参数列表,因此无法再次进行修改

fn2(1, 2); //bind:[object window]3

//bind方法不会调用原来的函数 可以改变原来函数内部的this指向

//返回的是原函数改变this之后产生的新函数

//例子:我们有一个按钮,当我们点击之后,就禁用这个按钮,3秒之后再开启这个按钮

varbtns=document.querySelectorAll('button');

for (vari=0; i<btns.length; i++) {

   btns[i].onclick=function() {

       this.disabled=true;

       setInterval(function() {

           this.disabled=false;

       }.bind(this), 3000); //这个this指向的是btn这个对象 在函数外面绑定一个bind,指向btn,就能解决定时器里面this指向问题

   }

}

总结
  • 相同点:都可以改变函数内部的this的指向
  • 不同点: call 和apply都会调用函数,但是他们传递的参数不一样,call传递参数arg1,arg2...形式 apply必须是数组形式[arg]
  • 主要应用场景:
  1. call经常做继承
  2. apply和数组有关系
  3. bind 不调用函数,但是想改变函数内部this指向

严格模式

什么是严格模式

JavaScript除了提供正常模式外,还提供了严格模式( strict mode )。ES5的严格模式是采用具有限制性JavaScript变体的一种方式,即在严格的条件下运行JS代码。

严格模式在IE10以上版本的浏览器中才会被支持,l旧版本浏览器中会被忽略。严格模式对正常的JavaScript语义做了一些更改∶

  1. 消除了Javascript语法的一些不合理、不严谨之处,减少了一些怪异行为。
  2. 消除代码运行的一些不安全之处,保证代码运行的安全。
  3. 提高编译器效率,增加运行速度。
  4. 禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的Javascript做好铺垫。比如一些保留字如:class, enum, export, extends, import, super不能做变量名
开启严格模式

严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况。

  1. 为脚本开启严格模式

为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句:

“use strict”;(或‘use strict' ;)。或者直接放在立即执行函数里面

  1. 为函数开启严格模式

要给某个函数开启严格模式,需要把“use strict”;(或'use strict';)声明放在函数体所有语句之前。

functionfn() {

   'use strict';

   //下面的代码按照严格模式执行

}

functionfun() {

   //里面的还是按照普通模式执行

}

严格模式中的变化

严格模式对Javascript的语法和行为,都做了一些改变。

在正常横式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,变量都必须先用var命令声明,然后再使用。

functionfff() {

   'use strict';

   num=10;

   console.log(num);

}

fff();//报错,变量没有申明

在严格模式中严禁删除已经申明的变量

varkano=1224;

deletekano; //报错,无法在严格模式中删除已经申明好的变量

严格模式下this指向问题

以前在全同作用域函数中的this指向window对象。严格模式下全局作用域中函数中的this是undefined。

以前构造函数时不加new也可以调用,当普通函数,this指向全局对象严格模式下,如果构造函数不加new调用, this会报错.

new 实例化的构造函数指向创建的对象实例。定时器this还是指向window 。

事件、对象还是指向调用者。

(function(){

   'use strict';

   functionffff() {

       console.log(this);//undefined

   }

   ffff();

   //在正常模式下构造函数可以当普通函数调用

   functionKano() {

       this.age=22

   } //严格模式下this指向的是undefined

   Kano();

   console.log(window.age); //严格模式下报错

   varkano=newKano();

   console.log(kano.age); //可以调用 显示22

   //定时器的this指向的还是window

   setTimeout(function(){

       console.log(this);

   },1000);

})()

函数变化

函数不能有重名的参数

函数必须声明在顶层新版本的JavaScript 会引入“块级作用域”(ES6中已引入)。为了与新版本接轨,不允许在非函数的代码块内声明函数。

//在普通模式下参数可以重名

   //a=1

   //a=2

   functionaa(a, a) {

       console.log(a+a);//2+2=4

   }

   aa(1, 2); //结果是4

   //但在严格模式下会直接报错Duplicate parameter name not allowed in this context

更多严格模式详情参考MDN严格模式

高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。

<script>

functionfn(callback){

   callback&&callback();

}

fn (function(){

   alert( "kanokano" )

}

</script>

//高阶函数-函数可以作为参数传递

functionfn(a, b, callback) {

   console.log(a+b);

   callback&&callback();

};

fn(1, 2, function() {

   console.log("OK");

});

在jQuery中的应用

$('div').animate({

   left: 500

},function(){//回调

  $("div").hide();

});

闭包

什么是闭包

闭包( closure )指有权访问另一个函数作用域中变量的函数。----- JavaScript高级程序设计

简单理解就是,一个作用域可以访问另外一个函数内部的局部变量 就叫闭包

functionfn() {

   varnum=199;

   functionfun() {

       console.log(num);

   }

}

以上函数就是一个闭包,因为fun函数访问了fn函数里面的局部变量

闭包的作用

functionfn() {

   varnum=199;

   returnfunction() {

       console.log(num);

   }

}

varf=fn();

f();

fn的调用,返回了function匿名函数,而匿名函数里面有fn的闭包,就可以实现在全局作用域下使用局部作用域的变量.

此时 num变量会在f函数全部执行完后才会销毁

闭包的主要作用,就是延申了变量的作用范围

利用闭包的方式得到li的当前索引号

varlis=document.querySelector("ul").querySelectorAll("li");

for (vari=0; i<lis.length; i++) {

   //利用for循环创建了四个立即执行函数

   (function(i) { //参数传入

       lis[i].onclick=function() {

           console.log(i);

       }

   })(i); //参数传入

}

闭包应用-1秒钟之后,打印li中的元素内容

varlis=document.querySelector("ul").querySelectorAll("li");

for (vari=0; i<lis.length; i++) {

   (function(i) { //参数传入

       setTimeout(function() {

           console.log(lis[i].innerHTML);

       }, 1000);

   })(i); //参数传入

}

立即执行函数也成为小闭包,因为立即执行函数里面的任何一个函数都可以使用他的变量

在某些情况下,闭包效率可能会比较低

闭包应用-计算打车价格

打车起步价13(3公里内),之后每多一公里增加5块钱.用户输入公里数就可以计算打车价格//如果有拥堵情况,总价格多收取10块钱拥堵费(这要价太黑了( )

//利用闭包计算租车价格

varcar= (function() {

   varstart=13; //起步价

   vartotal=0; //总价

   return {

       //正常的总价

       price: function(n) {

           if (n<=3) {

               total=start;

           } else {

               total=start+ (n-3) *5;

           }

           returntotal;

       },

       yd: function(flag) { //拥堵

           returnflag?total+10 : total;

       }

   }

})();

console.log(car.price(5)); //23

console.log(car.yd(true)); //33

思考题

如下,返回值是?

//思考题

varname="Window";

varobj= {

   name: "obj",

   getName: function() {

       returnfunction() {

           returnthis.name;

       };

   }

};

console.log(obj.getName()()); //window

//obj.getName()()

//相当于 var f = function() {

//            return this.name;

//        };

//所以this自然指向window

//而name变量是在window作用域内,所以是‘window’

函数里面没有局部变量,所以没有闭包的产生

结果为window

如果想使用obj的name,那就需要在函数内使用变量保存obj,这样才能产生闭包

varname="Window";

varobj= {

   name: "obj",

   getName: function() {

       varthat=this;//产生闭包

       returnfunction() {

           returnthat.name;

       };

   }

};

console.log(obj.getName()()); //obj

闭包总结
  • 闭包是一个函数(一个作用域可以访问另外一个函数的局部变量)
  • 闭包可以延申变量的作用域范围

递归

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

递归函数作用和循环效果是一致的

利用递归解决汉诺塔问题

functionH(n, one, two, three) {

   if (n==1) {

       console.log(one+" -> "+three);

   } else {

       H(n-1, one, three, two);

       console.log(one+" -> "+three);

       H(n-1, two, one, three);

   }

}

H(3, 'a', 'b', 'c');

利用递归遍历对象属性

vardata= [{

   id: 1,

   name: '家电',

   goods: [{

       id: 11,

       gname: '冰箱',

       goods: [{

           id: 111,

           gname: '冰箱1'

       }, {

           id: 122,

           gname: '洗衣机1'

       }]

   }, {

       id: 12,

       gname: '洗衣机'

   }]

}, {

   id: 2,

   name: '服饰'

}];

//输入id号,返回数据对象

functiongetID(json, id) {

   varo= {}; //创建一个空对象用于保存查找到的数据

   json.forEach(function(item) {

       if (item.id==id) {

           o=item; //给数据赋值

           returnitem; //返回查找到的数据给上层递归函数

       } elseif (item.goods&&item.goods.length>0) {

           o=getID(item.goods, id); //递归,并准备接受返回值

       }

   })

   returno;

}

console.log(getID(data, 1));

console.log(getID(data, 11));

console.log(getID(data, 111));


相关实践学习
一小时快速掌握 SQL 语法
本实验带您学习SQL的基础语法,快速入门SQL。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
JavaScript
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
27 0
|
2月前
|
消息中间件 Web App开发 JavaScript
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
70 0
|
3月前
|
监控 Linux Shell
【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(排查问题指令 - 下)
在线上排查问题时,查询日志、查看系统配置和分析操作系统信息是至关重要的。这些操作可以帮助我们深入了解软件和服务的兼容性,并解决潜在的问题。在本次学习中,我们将介绍并深入学习一些我在处理类似问题时常用的指令。通过掌握这些指令,你将能够更加高效地定位和解决线上问题,提高系统的稳定性和性能。让我们一同进入这个学习过程吧!
42 0
【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(排查问题指令 - 下)
|
1天前
|
JavaScript 前端开发 应用服务中间件
node.js之第一天学习
node.js之第一天学习
|
28天前
|
运维 JavaScript 前端开发
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
|
1月前
|
前端开发 搜索推荐 JavaScript
编程笔记 html5&css&js 001 学习编程从网页开始
编程笔记 html5&css&js 001 学习编程从网页开始
|
2月前
|
前端开发 JavaScript
从零开始学习前端开发:HTML、CSS、JavaScript入门指南
【2月更文挑战第1天】本文将带领读者从零开始学习前端开发,介绍HTML、CSS和JavaScript的基础知识与应用,帮助读者快速入门前端开发领域。
62 1
|
2月前
|
安全 Shell 网络安全
Git学习---Git快速入门、Git基础使用、Git进阶使用、Git服务器使用(IDEA集成GitHub、Gitee、GitLab)、GitHub Desktop客户端
Git学习---Git快速入门、Git基础使用、Git进阶使用、Git服务器使用(IDEA集成GitHub、Gitee、GitLab)、GitHub Desktop客户端
128 0
|
2月前
|
数据采集 机器学习/深度学习 JavaScript
画【Python折线图】的一百个学习报告(二、pyecharts引入js文件)
画【Python折线图】的一百个学习报告(二、pyecharts引入js文件)
47 0
|
2月前
|
JSON 前端开发 JavaScript
Webpack【Webpack图片处理、Webpack中proxy代理 、自动清理dist、Webpack优化、JavaScript中的代码检查】(三)-全面详解(学习总结---从入门到深化)
Webpack【Webpack图片处理、Webpack中proxy代理 、自动清理dist、Webpack优化、JavaScript中的代码检查】(三)-全面详解(学习总结---从入门到深化)
35 0
Webpack【Webpack图片处理、Webpack中proxy代理 、自动清理dist、Webpack优化、JavaScript中的代码检查】(三)-全面详解(学习总结---从入门到深化)