作者:一川来源:前端万有引力
文章插图
1 写在前面JAVAscript中的Apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关 。本篇文章我们将深入探讨这个关键词的作用,并尝试进行手动编写复现 。
阅读文章前,我们带着几个问题进行研究:
- 用什么样的思路可以new关键字?
- apply、bind、call这三个方法有什么区别?
- 怎样手动实现一个apply、bind和call?
2.1 new的原理使用new进行实例化对象,其步骤是:
- 创建一个新的空对象,即{}
- 将该对象构造函数的作用域赋给新对象,this指向新对象(即将新对象作为this的上下文)
- 执行构造函数中的代码,为这个新对象添加属性
- 如果该对象构造函数没有返回对象,则返回this
function Person(){this.name = "yichuan" }const p = new Person(); console.log(p.name);//"yichuan"
我们可以看到当使用new进行实例化时,可以将构造函数的this指向新对象p 。当不使用new时,此时构造函数的this指向window 。function Person(){this.name = "yichuan" }const p = Person(); console.log(p);//undefined console.log(name);//"yichuan"window.name console.log(p.name);//"yichuan" is undefined
当我们在构造函数中直接返回一个和this无关的对象时,使用new关键字进行实例化对象,新生成的对象就是构造函数返回的对象,而非构造函数的this的对象 。function Person(){this.name = "yichuan";return {age:18}; }const p = new Person(); console.log(p);//{age:18} console.log(p.name);//"undefined" console.log(p.age);/18
此外,当构造函数返回的不是一个对象,而是基础数据类型的值时,使用new创建新对象,会将构造函数返回的值以对象形式给新对象 。function Person(){this.name = "yichuan";return "onechuan"; }const p = new Person(); console.log(p);//{name:"yichuan"} console.log(p.name);//"yichuan"
new关键词执行之后总是会返回一个对象,要么是实例,要么是return语句指定的对象 。2.2 手写new的实现new被调用后大致做了哪些事情?
- 让实例可以访问私有属性
- 让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性
- 构造函数返回的最后结果是引用数据类型
function new_object(ctor,...args){//先要判断ctor是否为一个函数if(typeof ctor !== "function"){throw "ctor must be a function";}//创建一个空对象const obj = new Object();//将实例obj可以访问到ctor原型所在原型链的属性obj.__proto__ = Object.create(ctor.prototype);//将构造函数的this指向实例对象objconst res = ctor.apply(obj,...args);//确保最后new返回的是一个对象const isObject = typeof res === "object" && typeof res!== null;const isFunction = typeof res === "function";return isObject || isFunction ? res : obj; }
当然,我们还可以进行优化以下:function new_object() {// 1、获得构造函数,同时删除 arguments 中第一个参数const ctor = [].shift.call(arguments);//其实这里是借用了数组的shift方法// 2、创建一个空的对象并链接到原型,obj 可以访问构造函数原型中的属性const obj = Object.create(ctor.prototype);// 3、绑定 this 实现继承,obj 可以访问到构造函数中的属性const ret =ctor.apply(obj, arguments);// 4、优先返回构造函数返回的对象return ret instanceof Object ? ret : obj; };
3 apply、bind以及callapply、bind和call是挂载Function对象上的三个方法,调用这三个方法的必须是一个函数 。3.1 applyapply() 方法调用一个具有给定 this 值的函数,以及作为一个数组(或类似数组对象)提供的参数 。apply()方法可以改变函数this的指向,且立即执行函数 。
注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象 。如果传入类数组对象,它们会抛出异常 。
func.apply(thisArg, [param1,param2,...]);
在使用apply时,会将func的this指向改变为指向thisArg,然后以[param1,param2,...]参数数组作为参数输入 。func(["red","green","blue"]); func.apply(newFun, ["red","green","blue"]);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 有哪些不同的CSS前端框架可供选择?
- 专门针对chrome谷歌浏览器而开发的一款访问插件
- 什么叫TLD、gTLD、nTLD、ccTLD、iTLD 以及几者之间的关系
- 6个实用的 Python 自动化脚本,你学会了吗?
- 康乃馨的搭配方法,康乃馨与玫瑰搭配的花束图片
- 小菊花的品种,大菊花和小菊花功效区别
- 老倪青钱柳茶的功效与作用,老倪青钱柳茶的功效
- 菊花茶是什么样子的图片,香椿是什么样子图片
- 好运的向日葵微信头像,微信头像推荐
- 香薷治口臭原理,治口臭清毒素