<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--this的使用--> <!--(1)this的指向 作为对象的方法调用 作为普通函数调用 构造器调用 Function.prototype.call或Function.prototype.apply调用 --> <!--1)this作为对象的方法调用 当函数作为对象的方法被调用时,this指向该对象: --> <script> var obj = { a: 1, getA: function () { alert(this == obj); // true alert(this.a); //1 } } obj.getA(); // 2. 作为普通函数调用使用 window.name = "gloabalName"; var getName = function () { // 这哭的this指向的是window对象 return this.name; } var myObject = { name: "xiuxiu", getNameA: function () { // 这里的this指向的是myObject 对象 alert(this); // window return this.name; } } console.log(getName()); var a = myObject.getNameA; //globalName //console.log(a); // xiuxiu console.log(a()); var innerText = "我是全局变量的innerText"; // callback方法的使用 var button = document.createElement("button"); button.innerText = "打开"; button.id = "btn"; document.body.appendChild(button); button.onclick = function (ev) { // 定义一个that , 让这个that指向button对象 var that = this; // alert(this); button // 这里的this指向的是触发这个事件的那个对象 console.log(this.innerText); var callback = function () { // 这里的this指向的是window对象 // 注意:在ES5的strict模式下,this已经被规定不会指向全局对象,而是undefined console.log(this.innerText); //undifined // 这里的that 指向的是这个按钮对象, 不是window对象 console.log(that.innerText); } callback(); } //3. 构造器调用 // 构造器里的this就指向返回的这个对象 var myClass = function (name, sex) { this.name = name; this.sex = sex; alert(this.name + " " + this.sex); }; var male = new myClass("xiaohong", "male"); var myClass = function (name) { //console.log(this.name); //undifined this.name = name; console.log(this.name + " " + name); // 只有返回出去之后,这个name属性就会被外界修改 return { name: "hahaha" } } var cls = new myClass("xiuxiu"); alert(cls.name); // 4)Function.prototype.call和Function.prototype.apply调用 // 跟普通的函数调用相比,用Function.prototype.call或Function.prototype.apply可以动态的改变传入函数的this var obj1 = { name: "xiuxiu", getName: function () { return this.name; } } var obj2 = { name: "Jack" } console.log(obj1.name); // xiuxiu console.log(obj1.getName.call(obj2)); // jack var obj3 = { myname: "seven", getName: function () { return this.myname; } } // 此时在调用this指向 obj3对象 console.log(obj3.getName()); // seven // 修改this的指向 // 这里是通过getname2这个普通函数区调用的, 此时this 指向的是window对象 // 但是全局中没有getname2这个方法 var getname2 = obj3.getName; alert(getname2()); //undifined // document.getElementById的使用错误 var getId = function (id) { //alert(this); // 这里的this指向的widnow return document.getElementById(id); } var id = getId("btn"); console.log("id:" + id); // ButtonElement // 这里把这个函数的this修改为指向document对象 //var getId = document.getElementById; //id = getId("btn"); //console.log("id:"+id); // this的使用理解.html?_ijt=7mjupf008evikdgvnqbeddk23d:146 Uncaught TypeError: Illegal invocation // 手动修改this 的指向 document.getElementById = (function (func) { return function () { // 这里强制让func对象指向documen对象 return func.apply(document, arguments); } })(document.getElementById); var getId = document.getElementById; var button = getId("btn"); console.log(button); // <button id="btn">打开</button> console.log(button.id); // 二、call和apply的使用 var func = function (a, b, c) { "use strict"; // 显示一下这个函数体内的this指向是个啥 alert(this); console.log([a, b, c]); } // ƒ (a, b, c) { /*console.log([a, b, c]); }*/ console.log(func); // func()表示直接去调用这个函数 console.log(func()); // undifined // 通过apply方法可以去修改这个函数体内的 this 的指向,可以任意修改, window, document // 第一个参数也是代表函数体内的this指向,从第二个参数开始往后,每个参数被依次传入函数 func.apply(null, [1, 2, 3]); // this指向window // 在严格模式"use strict"下上面的this指向为null, 不使用严格模式会指向window func.apply(null, [1]); // this指向window //如果我们传入的第一个参数为null,函数体内的this会指向默认的宿主对象。在浏览器中则是window func.apply(null, [0, 1]); // this指向window //console.log(func()); func.apply(document, [0, 1, 2]); // this指向document func.apply(this, [0, 1]); // this指向window // 利用函数求出最大值 console.log(Math.max.apply(null, [1, 2, 3])); console.log(Math.max(1, 2, 3)); // 三、call和apply在实际开发中的用途 // 1.)修改 this的指向 var obj1 = { //alert(this); name: "seven" } var obj2 = { //alert(this); name: "haha" } window.name = "window"; var getName = function () { console.log(this.name); } // 全局调用函数 getName(); // this指向的是window getName.call(obj1); // this指向的是obj1对象 getName.call(obj2); // this指向的是obj2对象 // 添加一个事件 document.addEventListener("click", function (ev) { // 这里的this 指向的是触发这个事件的那个对象 console.log(this); // document function Add(a, b) { console.log(this); } // 这个相当于是全局调用,thisz指向的是window对象 Add(10, 1); // window // 修正这个this 的指向 // 这里的this指向的还是触发这个事件的那个对象 Add.call(this); // document }); // 2).Function.prototype.bind // Function.prototype.bind,用来指定函数内部的this指向 Function.prototypebind = function (context) { var self = this; return function () { console.log(context+"is"+ this); // 修改this(self)的指向为context对象 return self.apply(context, arguments); } } var obj = { name: "xiuxiuDesign" } var getName = function () { // 修改this的指向为obj对象 console.log(this.name); }.bind(obj); getName(); // 3).借用其它对象的方法 var A = function (name) { this.name = name; } var B = function () { // 修改A这个的this对象指向B A.apply(this, arguments); // Arguments ["xiuxiu is a good man", callee: ƒ, Symbol(Symbol.iterator): ƒ] console.log(arguments); } B.prototype.getName = function () { // return this.name; } var b = new B("xiuxiu is a good man"); console.log(b.getName()); // 想往argumments中添加一个新的元素,通常会借用Array.prototype.push (function () { Array.prototype.push.call(arguments, 3); console.log(arguments); })(1, 2, 1, 3) // 想把arguments转成真正的数组的时候,可以借用Array.prototype.slice方法,想截取arguments列表中的头一个元素时,可以使用Array.prototype.shift方法,这种机制的内部原理,我们可以翻开V8引擎源码,以Array.prototype.push方法为例 var a = {}; // 修改Array这个数组的指向, 让这个数组的push的this指向a的引用, 也就是a这个对象 Array.prototype.push.call(a, 'first'); Array.prototype.push.call(a, 'second'); // 通过调用Array的push 方法, 同时修改了this 的指向为a这个对象的引用 console.log(a.length); console.log(a[0]); // JavaScript的一种继承方式 var AA = function (name, age) { this.name = name; this.age = age; } AA.prototype = { getName : function () { alert(this.name); } } var BB = function () { } // 让BB对象继承于AA对象 BB.prototype = new AA("AAA", 19); var aa = new AA("xiuxiu", 18); console.log(aa.name +" "+aa.age); // xiuxiu, 18 var bb = new BB(); console.log(bb.name+" "+bb.age); // AAA 19 </script> </body> </html>