JavaScript学习记录十七

 2023-09-05 阅读 69 评论 0

摘要:apply和call方法的使用 //apply和call的使用 //作用:可以改变this的指向 //apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是默认的window *JavaScript中存在继承,通过调用apply或call传过去的第一个参数来动态指定方法中的 t

apply和call方法的使用

    //apply和call的使用
    //作用:可以改变this的指向

    //apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是默认的window

    *JavaScript中存在继承,通过调用apply或call传过去的第一个参数来动态指定方法中的 this .

    function f1(x,y) {console.log("结果是:"+(x+y)+this);return "10000";}f1.apply();f1.call();f1.apply(null);f1.call(null);apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的f1.apply(null,[100,200]);f1.call(null,100,200);

apply和call的使用方法
    /*
    * apply的使用语法
    * 函数名字.apply(对象,[参数1,参数2,...]);
    * 方法名字.apply(对象,[参数1,参数2,...]);
    * call的使用语法
    * 函数名字.call(对象,参数1,参数2,...);
    * 方法名字.call(对象,参数1,参数2,...);
    *
    * 作用:改变this的指向
    * 不同的地方:参数传递的方式是不一样的

    * 只要是想使用别的对象的方法,并且希望这个方法是当前对象的,那么就可以使用apply或者是call的方法改变this的指向

        function f1() {console.log(this+":====>调用了");}f1是函数,f1也是对象,因为f1中有 __proto__和prototypeconsole.dir(f1);对象调用方法,说明,该对象中有这个方法f1.apply();f1.call();console.log(f1.__proto__==Function.prototype);所有的函数都是Function的实例对象console.log(Function.prototype);//ƒ () { [native code] }console.dir(Function);apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype中
bind是用来复制一份
//使用的语法:
/*理解:将改变this后的函数状态复制了一份。函数调用之后内部this使用的是指定后的
* 函数名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个函数
* 方法名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个方法
    function Person(age) {this.age=age;}Person.prototype.play=function () {console.log(this+"====>"+this.age);};function Student(age) {this.age=age;}var per=new Person(10);var stu=new Student(20);//复制了一份var ff=per.play.bind(stu);ff();  [object Object]====>20

bind方法的使用

  <script>通过对象,调用方法,产生随机数function ShowRandom() {1-10的随机数this.number=parseInt(Math.random()*10+1);}添加原型方法ShowRandom.prototype.show1=function () {改变了定时器中的this的指向了,本来应该是window,现在是实例对象了window.setInterval(this.show2.bind(this),1000);};添加原型方法ShowRandom.prototype.show2=function () {显示随机数--console.log(this.number);};实例对象var sr=new ShowRandom();调用方法,输出随机数字调用这个方法一次,可以不停的产生随机数字sr.show1();</script>

函数中的几个成员

    //函数中有一个name属性----->函数的名字,name属性是只读的,不能修改
    //函数中有一个arguments属性--->实参的个数
    //函数中有一个length属性---->函数定义的时候形参的个数
    //函数中有一个caller属性---->调用(f1函数在f2函数中调用的,所以,此时调用者就是f2)

    function f1(x,y) {console.log(f1.name);console.log(f1.arguments.length);console.log(f1.length);console.log(f1.caller);//调用者}

函数还可以通过参数传递来实现调用,在函数体中执行函数

           function f1(fn) {setInterval(function () {console.log("定时器开始");fn();console.log("定时器结束");},1000);}f1(function () {console.log("好困啊,好累啊,就是想睡觉");});

函数作为返回值

           可以参考java中设置toString方法进行理解var num=10;console.log(typeof num);  numbervar obj={};console.log(obj instanceof Object);  true更改this为obj,直接打印obj的使用会显示其数据类型Object.prototype.toString.call(obj);console.log(obj)  {}获取数据类型,修改this指向具体类型数据,通过toString方法进行打印console.log(Object.prototype.toString.call([]));  [object Array]console.log(Object.prototype.toString.call(new Date()));  [object Date]函数作为返回值的使用function getFunc(type) {return function (obj) {return Object.prototype.toString.call(obj) === type;}}var ff = getFunc("[object Array]");var result = ff([10, 20, 30]);console.log(result);  true

函数作为参数练习,有点像java中的重写equals方法

    *sort方法会从零号位置进行遍历和比较,如果返回值大于零,则进行交换。

    var arr = [1, 100, 20, 200, 40, 50, 120, 10];//排序---函数作为参数使用,匿名函数作为sort方法的参数使用,那么此时的匿名函数中有两个参数,arr.sort(function (obj1,obj2) {if(obj1>obj2){return -1;}else if(obj1==obj2){return 0;}else{return 1;}});console.log(arr);var arr1=["acdef","abcd","bcedf","bced"];arr1.sort(function (a,b) {if(a>b){return 1;}else if(a==b){return 0;}else{return -1;}});console.log(arr1);

案例:函数作为参数

    function File(name, size, time) {this.name = name;//电影名字this.size = size;//电影大小this.time = time;//电影的上映时间}var f1 = new File("jack.avi", "400M", "1997-12-12");var f2 = new File("tom.avi", "200M", "2017-12-12");var f3 = new File("xiaosu.avi", "800M", "2010-12-12");var arr = [f1, f2, f3];function fn(attr) {//函数作为返回值return function getSort(obj1, obj2) {if (obj1[attr] > obj2[attr]) {return 1;} else if (obj1[attr] == obj2[attr]) {return 0;} else {return -1;}}}var ff = fn("name");//函数作为参数arr.sort(ff);for (var i = 0; i < arr.length; i++) {console.log(arr[i].name + "====>" + arr[i].size + "===>" + arr[i].time);}

作用域和作用域链和预解析

    //变量---->局部变量和全局变量,
    //作用域:就是变量的使用范围
    //局部作用域和全局作用域
    //js中没有块级作用域---一对括号中定义的变量,这个变量可以在大括号外面使用
    //函数中定义的变量是局部变量

        if(true){var num=10;}console.log(num)    10function fn() {var num2=20;}console.log(num2);  报异常 num2 is not defined

    作用域链:变量的使用,从里向外,层层的搜索,搜索到了就可以直接使用了层层搜索,搜索到0级作用域的时候,如果还是没有找到这个变量,结果就是报错

    *如果里层没有对应的变量,它会一层一层想外查找

        var num=10;function f() {var num=20;function f1() {var num=30;console.log(num);}f1();}f();

    //预解析:就是在浏览器解析代码之前,把变量的  声明  和  函数的声明  提前(提升)到该作用域的最上面

        console.log(num);var num=10;   undefined 声明提前了,但是没有初始化f();   函数执行了,预解析函数提前了function f() {console.log('函数执行了')}console.log(f1); undefined 函数的声明提前了var f1=function() {console.log('声明提前了')}

闭包
    * 闭包的概念:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者是数据,此时形成了闭包(这句话暂时不严谨)
    * 闭包的模式:函数模式的闭包,对象模式的闭包
    * 闭包的作用:缓存数据,延长作用域链
    * 闭包的优点和缺点:缓存数据

        函数模式的闭包:在一个函数中有一个函数function f1() {var num=10;//函数的声明function f2() {console.log(num);  10}//函数调用f2();}f1();对象模式的闭包:函数中有一个对象function f3() {var num=10;var obj={age:num};console.log(obj.age);//10}f3();

闭包小练习

        function f() {var num=10;return function(){num++;return num;}}var fn=f();console.log(fn()); 11console.log(fn()); 12console.log(fn()); 13

总结:如果想要缓存数据,就把这个数据放在外层的函数和里层的函数的中间位置

    //闭包的作用:缓存数据.优点也是缺陷,没有及时的释放

    //局部变量是在函数中,函数使用结束后,局部变量就会被自动的释放
    //闭包后,里面的局部变量的使用作用域链就会被延长

    function showRandom() {var num=parseInt(Math.random()*10+1);console.log(num);}showRandom();showRandom();showRandom();实现了缓存功能的闭包,多次调用打印的数字都一样function f1() {var num=parseInt(Math.random()*10+1);return function () {console.log(num);}}var ff=f1();ff();ff();ff();

案例:点赞小案例

  <style>ul {list-style-type: none;}li {float: left;margin-left: 10px;}img {width: 200px;height: 180px;}input {margin-left: 30%;}</style><script>//$永远都是24k纯帅的十八岁的杨哥$</script>
</head>
<body>
<ul><li><img src="images/ly.jpg" alt=""><br/><input type="button" value="赞(1)"></li>...若干个...
</ul>
<script>//获取所有的按钮//根据标签名字获取元素function my$(tagName) {return document.getElementsByTagName(tagName);}//闭包缓存数据function getValue() {var value=2;return function () {//每一次点击的时候,都应该改变当前点击按钮的value值this.value="赞("+(value++)+")";}}//获取所有的按钮var btnObjs=my$("input");//循环遍历每个按钮,注册点击事件for(var i=0;i<btnObjs.length;i++){//注册事件btnObjs[i].onclick=getValue();}

       沙箱:环境,黑盒,在一个虚拟的环境中模拟真实世界,做实验,实验结果和真实世界的结果是一样,但是不会影响真实世界

    var num=10;(function () {var num=20;console.log(num+10);  30})();

沙箱小案例

    (function () {document.getElementById('btn').onclick=function () {console.log('按钮被点击了')}})();(function () {var str='我是中国人';console.log(str.substr(2))   中国人})();

沙箱小案例

<div>这是div</div>
<div>这是div</div>
<p>这是p</p>
<p>这是p</p>
<script>var getTag = 10;var dvObjs = 20;var pObjs = 30;(function () {//根据标签名字获取元素function getTag(tagName) {return document.getElementsByTagName(tagName)}//获取所有的divvar dvObjs = getTag("div");for (var i = 0; i < dvObjs.length; i++) {dvObjs[i].style.border = "2px solid pink";}//获取所有的pvar pObjs = getTag("p");for (var i = 0; i < pObjs.length; i++) {pObjs[i].style.border = "2px solid pink";}}());console.log(getTag);  10console.log(dvObjs);  20console.log(pObjs);   20

递归:函数中调用函数自己,此时就是递归,递归一定要有结束的条件

        function f(n) {if(n==1){return 1;}return n+f(n-1);}console.log(f(10));

 

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/902.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息