深究JavaScript——apply、call

本文详细介绍了JavaScript中apply与call方法的区别与应用场景,包括如何通过这两个方法实现对象属性与方法的借用,构造器的连接,以及数组操作等。

apply: 方法在指定 this 值和参数(参数以数组或类数组对象的形式存在)的情况下调用某个函数。能劫持另外一个对象的方法,继承另外一个对象的属性。

  1. Function.apply(obj,args)

        obj:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。

        args:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给Function函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。

  1. //定义一个Person类
  2. function Person(name, sex){
  3. this.name = name;
  4. this.sex = sex;
  5. }
  6. //定义一个Engineer类
  7. function Engineer(name, sex, appearance){
  8. Person.apply(this, arguments);
  9. this.appearance = appearance;
  10. }
  11. //创建一个Engineer类
  12. var eng = new Engineer("staven", "男", "handsome");
  13. console.log(eng.name+"是一位"+eng.appearance+"的"+eng.sex+"士!");  //staven是一位handsome的男士!

        可理解为当前的this代表的Engineer对象去借用Person类的属性与方法,这样自己也就拥有了这些属性与方法的使用权。

         Function.apply(obj,args)方法能接收两个参数。obj:这个对象将代替Function类里this对象;args:这个是数组,它将作为参数传给Function(args-->arguments)。

  1. foo.call(this, arg1, arg2, arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)


apply与call的异同

apply:

  1. Function.apply(obj, args)

call:

  1. Function.apply(obj, arg1, arg2, ……)

        相同点:两个方法产生的作用是完全一样的。

        不同点:从第二个参数起, call方法参数将依次传递给借用的方法作参数, 而apply直接将这些参数放到一个数组中再传递, 最后借用方法的参数列表是一样的.

apply使用场景:

使用apply来连接构造器

  1. Function.prototype.say = function(args){
  2. var that = this,
  3. newObj = function(){
  4. that.apply(this, args);
  5. }
  6. newObj.prototype = that.prototype;
  7. return new newObj();
  8. }
  9. function sayArgs(){
  10. for(var i=0; i<arguments.length; i++){
  11. this["arg"+i] = arguments[i];
  12. }
  13. }
  14. var argsArr = ["hello","staven","handsome man"];
  15. var p = sayArgs.say(argsArr);
  16. console.log(p.arg1); //staven 
  1. Function.prototype.say = function(args){
  2. var newObj = Object.create(this.prototype);
  3. this.apply(newObj, args);
  4. return newObj;
  5. }
  6. function sayArgs(){
  7. for(var i=0; i<arguments.length; i++){
  8. this["arg"+i] = arguments[i];
  9. }
  10. }
  11. var argsArr = ["hello","staven","handsome man"];
  12. var p = sayArgs.say(argsArr);
  13. console.log(p.arg1);

 apply参数逐个解析

        调用apply方法的时候apply(obj,args),="" 第二个参数args是一个数组集合,仍然将会解析为一个一个的参数,这个就是apply的一个巧妙的用处。利用这个特性可以用于一些特殊的场景。

math.max()得到数组中最大的一项。

        math.max()函数用于返回一个或多个数中最大的数。如果没有传入任何参数,则返回负的无穷大(-infinity);如果参数中存在为nan的值,则返回nan。

        math.max()并不支持数组。传统方式获取数组中最大值:

  1. var arr = [4,5,32,9,231,2,56];
  2. function getMaxVal(arr){
  3. var arrLen = arr.length;
  4. for (var i=0,initVal=arr[0]; i<arrLen; i++) {
  5. initVal = Math.max(initVal, arr[i]);
  6. }
  7. return initVal;
  8. }
  9. console.log(getMaxVal(arr)); //231

        使用apply,可有效简化操作步骤:

  1. var arr = [4,5,32,9,231,2,56];
  2. console.log(Math.max.apply(null, arr)); //231

Array.prototype.push可以实现两个数组合并

        push()方法可向数组的末尾添加一个或多个元素,并返回新的长度。

  1. var arr1 = [1,2,3];
  2. var arr2 = [4,5,6];
  3. arr1.push(arr2)
  4. console.log(arr1); //[1, 2, 3, Array[3]]

        concat()="" 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

  1. var arr1 = [1,2,3];
  2. var arr2 = [4,5,6];
  3. console.log(arr1.concat(arr2)); //[1, 2, 3, 4, 5, 6]
  4. console.log(arr1); //[1, 2, 3]

        若想将arr1、arr2合并到arr1中,显然上面两个方法实现不了。但可以这样做。

  1. var arr1 = [1,2,3];
  2. var arr2 = [4,5,6];
  3. arr1 = arr1.concat(arr2);
  4. console.log(arr1); //[1, 2, 3, 4, 5, 6]

        再来看看使用apply如何实现的:

  1. var arr1 = [1,2,3];
  2. var arr2 = [4,5,6];
  3. Array.prototype.push.apply(arr1, arr2);
  4. console.log(arr1); //[1, 2, 3, 4, 5, 6]

call的应用场景

使用call方法调用父构造函数

  1. //定义一个Person类
  2. function Person(name, sex){
  3. this.name = name;
  4. this.sex = sex;
  5. }
  6. //定义一个Engineer类
  7. function Engineer(name, sex, appearance){
  8. Person.call(this, name, sex);
  9. this.appearance = appearance;
  10. }
  11. Engineer.prototype = Object.create(Person.prototype);
  12. Engineer.prototype.constructor = Engineer;
  13. //创建一个Engineer类
  14. var eng = new Engineer("staven", "男", "handsome");
  15. console.log(eng.name+"是一位"+eng.appearance+"的"+eng.sex+"士!");  //staven是一位handsome的男士!

使用call方法调用匿名函数

  1. var person = [
  2. {name:"staven",appearance:"handsome",sex:"man"},
  3. {name:"赫连小妖",appearance:"spirited",sex:"man"}
  4. ];
  5. for (var i=0;i<person.length; i++) {
  6. (function(i){
  7. this.say = function(){
  8. console.log(this.name+"是个非常"+this.appearance+"的"+this.sex);
  9. }
  10. this.say();
  11. }).call(person[i],i);
  12. }
  13. //staven是个非常handsome的man
  14. //赫连小妖是个非常spirited的man

使用call方法调用匿名函数并且指定上下文的'this'

  1. function say(){
  2. var content = [this.name,"是个非常",this.appearance,"的"+this.sex].join("");
  3. console.log(content);
  4. }
  5. var person = {
  6. name:"staven",
  7. appearance:"handsome",
  8. sex:"man"
  9. }
  10. say.call(person); //staven是个非常handsome的man
本指南详细阐述基于Python编程语言结合OpenCV计算机视觉库构建实时眼部状态分析系统的技术流程。该系统能够准确识别眼部区域,并对眨眼动作与持续闭眼状态进行判别。OpenCV作为功能强大的图像处理工具库,配合Python简洁的语法特性与丰富的第三方模块支持,为开发此类视觉应用提供了理想环境。 在环境配置阶段,除基础Python运行环境外,还需安装OpenCV核心模块与dlib机器学习库。dlib库内置的HOG(方向梯度直方图)特征检测算法在面部特征定位方面表现卓越。 技术实现包含以下关键环节: - 面部区域检测:采用预训练的Haar级联分类器或HOG特征检测器完成初始人脸定位,为后续眼部分析建立基础坐标系 - 眼部精确定位:基于已识别的人脸区域,运用dlib提供的面部特征点预测模型准确标定双眼位置坐标 - 眼睑轮廓分析:通过OpenCV的轮廓提取算法精确勾勒眼睑边缘形态,为状态判别提供几何特征依据 - 眨眼动作识别:通过连续帧序列分析眼睑开合度变化,建立动态阈值模型判断瞬时闭合动作 - 持续闭眼检测:设定更严格的状态持续时间与闭合程度双重标准,准确识别长时间闭眼行为 - 实时处理架构:构建视频流处理管线,通过帧捕获、特征分析、状态判断的循环流程实现实时监控 完整的技术文档应包含模块化代码实现、依赖库安装指引、参数调优指南及常见问题解决方案。示例代码需具备完整的错误处理机制与性能优化建议,涵盖图像预处理、光照补偿等实际应用中的关键技术点。 掌握该技术体系不仅有助于深入理解计算机视觉原理,更为疲劳驾驶预警、医疗监护等实际应用场景提供了可靠的技术基础。后续优化方向可包括多模态特征融合、深度学习模型集成等进阶研究领域。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值