- 浏览: 7947651 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (2425)
- 软件工程 (75)
- JAVA相关 (662)
- ajax/web相关 (351)
- 数据库相关/oracle (218)
- PHP (147)
- UNIX/LINUX/FREEBSD/solaris (118)
- 音乐探讨 (1)
- 闲话 (11)
- 网络安全等 (21)
- .NET (153)
- ROR和GOG (10)
- [网站分类]4.其他技术区 (181)
- 算法等 (7)
- [随笔分类]SOA (8)
- 收藏区 (71)
- 金融证券 (4)
- [网站分类]5.企业信息化 (3)
- c&c++学习 (1)
- 读书区 (11)
- 其它 (10)
- 收藏夹 (1)
- 设计模式 (1)
- FLEX (14)
- Android (98)
- 软件工程心理学系列 (4)
- HTML5 (6)
- C/C++ (0)
- 数据结构 (0)
- 书评 (3)
- python (17)
- NOSQL (10)
- MYSQL (85)
- java之各类测试 (18)
- nodejs (1)
- JAVA (1)
- neo4j (3)
- VUE (4)
- docker相关 (1)
最新评论
-
xiaobadi:
jacky~~~~~~~~~
推荐两个不错的mybatis GUI生成工具 -
masuweng:
(转)JAVA获得机器码的实现 -
albert0707:
有些扩展名为null
java 7中可以判断文件的contenttype了 -
albert0707:
非常感谢!!!!!!!!!
java 7中可以判断文件的contenttype了 -
zhangle:
https://zhuban.me竹板共享 - 高效便捷的文档 ...
一个不错的网络白板工具
http://blog.leapoahead.com/2015/08/31/understanding-js-this-keyword/
小明正在跑步,他看起来很开心
这里的小明是主语,如果没有这个主语,那么后面的代词『他』将毫无意义。有了主语,代词才有了可以指代的事物。
类比到JavaScript的世界中,我们在调用一个对象的方法的时候,需要先指明这个对象,再指明要调用的方法。
var xiaoming = {
name: 'Xiao Ming',
run: function() {
console.log(`${this.name} seems happy`);
},
};
xiaoming.run();
在线演示
在上面的例子中,第8行中的xiaoming指定了run方法运行时的主语。因此,在run中,我们才可以用this来代替xiaoming这个对象。可以看到this起了代词的作用。
同样的,对于一个JavaScript类,在将它初始化之后,我们也可以用类似的方法来理解:类的实例在调用其方法的时候,将作为主语,其方法中的this就自然变成了指代主语的代词。
class People {
constructor(name) {
// 在用new关键字实例化一个对象的时候,相当于在说,
// “创建一个People类实例(主语),它(this)的name是……”
// 所以这里的this就是新创建的People类实例
this.name = name;
}
run() {
console.log(`${this.name} seems happy.`)
}
}
// new关键字实例化一个类
var xiaoming = new People('xiaoming');
xiaoming.run();
在线演示
这就是我认为this关键字设计得精彩的地方!如果将调用方法的语句(上面代码的第16行)和方法本身的代码连起来,像英语一样读,其实是完全通顺的。
this的绑定
句子的主语是可以变的,例如在下面的场景中,run被赋值到小芳(xiaofang)身上之后,调用xiaofang.run,主语就变成了小芳!
var xiaofang = {
name: 'Xiao Fang',
};
var xiaoming = {
name: 'Xiao Ming',
run: function() {
console.log(`${this.name} seems happy`);
},
};
xiaofang.run = xiaoming.run;
// 主语变成了小芳
xiaofang.run();
在线演示
在这种情况下,句子还是通顺的。所以,非常完美!
非常完美!
但是如果小明很抠门,不愿意将run方法借给小芳以后,this就变成了小芳的话,那么小明要怎么做呢?他可以通过Function.prototype.bind让run运行时候的this永远为小明自己。
var xiaofang = {
name: 'Xiao Fang',
};
var xiaoming = {
name: 'Xiao Ming',
run: function() {
console.log(`${this.name} seems happy`);
},
};
// 将小明的run方法绑定(bind)后,返回的还是一个
// 函数,但是这个函数之后被调用的时候就算主语不是小明,
// 它的this依然是小明
xiaoming.run = xiaoming.run.bind(xiaoming);
xiaofang.run = xiaoming.run;
// 主语虽然是小芳,但是最后this还是小明
xiaofang.run();
在线演示
那么同一个函数被多次bind之后,到底this是哪一次bind的对象呢?你可以自己尝试看看。
call与apply
Function.prototype.call允许你在调用一个函数的时候指定它的this的值。
var xiaoming = {
name: 'Xiao Ming'
};
function run(today, mood) {
console.log(`Today is ${today}, ${this.name} seems ${mood}`);
}
// 函数的call方法第一个参数是this的值
// 后续只需按函数参数的顺序传参即可
run.call(xiaoming, 'Monday', 'happy')
在线演示
Function.prototype.apply和Function.prototype.call的功能是一模一样的,区别进在于,apply里将函数调用所需的所有参数放到一个数组当中。
2
var xiaoming = {
name: 'Xiao Ming'
};
function run(today, mood) {
console.log(`Today is ${today}, ${this.name} seems ${mood}`);
}
// apply只接受两个参数
// 第二个参数是一个数组,这个数组的元素被按顺序
// 作为run调用的参数
run.apply(xiaoming, ['Monday', 'happy'])
在线演示
那么call/apply和上面的bind混用的时候是什么样的行为呢?这个也留给大家自行验证。但是在一般情况下,我们应该避免混用它们,否则会造成代码检查或者调试的时候难以跟踪this的值的问题。
当方法失去主语的时候,this不再有?
其实大家可以发现我的用词,当一个function被调用的时候是有主语的时候,它是一个方法;当一个function被调用的时候是没有主语的时候,它是一个函数。当一个函数运行的时候,它虽然没有主语,但是它的this的值会是全局对象。在浏览器里,那就是window。当然了,前提是函数没有被bind过,也不是被apply或call所调用。
那么function作为函数的情景有哪些呢?
首先,全局函数的调用就是最简单的一种。
function bar() {
console.log(this === window); // 输出:true
}
bar();
立即调用的函数表达式(IIFE,Immediately-Invoked Function Expression)也是没有主语的,所以它被调用的时候this也是全局对象。
(function() {
console.log(this === window); // 输出:true
})();
在线演示(包含上面两个例子)
但是,当函数被执行在严格模式(strict-mode)下的时候,函数的调用时的this就是undefined了。这是很值得注意的一点。
function bar() {
'use strict';
console.log('Case 2 ' + String(this === undefined)); // 输出:undefined
}
bar();
不可见的调用
有时候,你没有办法看到你定义的函数是怎么被调用的。因此,你就没有办法知道它的主语。下面是一个用jQuery添加事件监听器的例子。
window.val = 'window val';
var obj = {
val: 'obj val',
foo: function() {
$('#text').bind('click', function() {
console.log(this.val);
});
}
};
obj.foo();
在线演示
在事件的回调函数(第6行开始定义的匿名函数)里面,this的值既不是window,又不是obj,而是页面上id为text的HTML元素。
var obj = {
foo: function() {
$('#text').bind('click', function() {
console.log(this === document.getElementById('text')); // 输出:true
});
}
};
obj.foo();
在线演示
这是因为匿名函数是被jQuery内部调用的,我们不知道它调用的时候的主语是什么,或者是否被bind等函数修改过this的值。所以,当你将匿名函数交给程序的其他部分调用的时候,需要格外地谨慎。
如果我们想要在上面的回调函数里面使用obj的val值,除了直接写obj.val之外,还可以在foo方法中用一个新的变量that来保存foo运行时this的值。这样说有些绕口,我们看下例子便知。
window.val = 'window val';
var obj = {
val: 'obj val',
foo: function() {
var that = this; // 保存this的引用到that,这里的this实际上就是obj
$('#text').bind('click', function() {
console.log(that.val); // 输出:obj val
});
}
};
obj.foo();
在线演示
另外一种方法就是为该匿名函数bind了。
window.val = 'window val';
var obj = {
val: 'obj val',
foo: function() {
$('#text').bind('click', function() {
console.log(this.val); // 输出:obj val
}.bind(this));
}
};
obj.foo();
小明正在跑步,他看起来很开心
这里的小明是主语,如果没有这个主语,那么后面的代词『他』将毫无意义。有了主语,代词才有了可以指代的事物。
类比到JavaScript的世界中,我们在调用一个对象的方法的时候,需要先指明这个对象,再指明要调用的方法。
var xiaoming = {
name: 'Xiao Ming',
run: function() {
console.log(`${this.name} seems happy`);
},
};
xiaoming.run();
在线演示
在上面的例子中,第8行中的xiaoming指定了run方法运行时的主语。因此,在run中,我们才可以用this来代替xiaoming这个对象。可以看到this起了代词的作用。
同样的,对于一个JavaScript类,在将它初始化之后,我们也可以用类似的方法来理解:类的实例在调用其方法的时候,将作为主语,其方法中的this就自然变成了指代主语的代词。
class People {
constructor(name) {
// 在用new关键字实例化一个对象的时候,相当于在说,
// “创建一个People类实例(主语),它(this)的name是……”
// 所以这里的this就是新创建的People类实例
this.name = name;
}
run() {
console.log(`${this.name} seems happy.`)
}
}
// new关键字实例化一个类
var xiaoming = new People('xiaoming');
xiaoming.run();
在线演示
这就是我认为this关键字设计得精彩的地方!如果将调用方法的语句(上面代码的第16行)和方法本身的代码连起来,像英语一样读,其实是完全通顺的。
this的绑定
句子的主语是可以变的,例如在下面的场景中,run被赋值到小芳(xiaofang)身上之后,调用xiaofang.run,主语就变成了小芳!
var xiaofang = {
name: 'Xiao Fang',
};
var xiaoming = {
name: 'Xiao Ming',
run: function() {
console.log(`${this.name} seems happy`);
},
};
xiaofang.run = xiaoming.run;
// 主语变成了小芳
xiaofang.run();
在线演示
在这种情况下,句子还是通顺的。所以,非常完美!
非常完美!
但是如果小明很抠门,不愿意将run方法借给小芳以后,this就变成了小芳的话,那么小明要怎么做呢?他可以通过Function.prototype.bind让run运行时候的this永远为小明自己。
var xiaofang = {
name: 'Xiao Fang',
};
var xiaoming = {
name: 'Xiao Ming',
run: function() {
console.log(`${this.name} seems happy`);
},
};
// 将小明的run方法绑定(bind)后,返回的还是一个
// 函数,但是这个函数之后被调用的时候就算主语不是小明,
// 它的this依然是小明
xiaoming.run = xiaoming.run.bind(xiaoming);
xiaofang.run = xiaoming.run;
// 主语虽然是小芳,但是最后this还是小明
xiaofang.run();
在线演示
那么同一个函数被多次bind之后,到底this是哪一次bind的对象呢?你可以自己尝试看看。
call与apply
Function.prototype.call允许你在调用一个函数的时候指定它的this的值。
var xiaoming = {
name: 'Xiao Ming'
};
function run(today, mood) {
console.log(`Today is ${today}, ${this.name} seems ${mood}`);
}
// 函数的call方法第一个参数是this的值
// 后续只需按函数参数的顺序传参即可
run.call(xiaoming, 'Monday', 'happy')
在线演示
Function.prototype.apply和Function.prototype.call的功能是一模一样的,区别进在于,apply里将函数调用所需的所有参数放到一个数组当中。
2
var xiaoming = {
name: 'Xiao Ming'
};
function run(today, mood) {
console.log(`Today is ${today}, ${this.name} seems ${mood}`);
}
// apply只接受两个参数
// 第二个参数是一个数组,这个数组的元素被按顺序
// 作为run调用的参数
run.apply(xiaoming, ['Monday', 'happy'])
在线演示
那么call/apply和上面的bind混用的时候是什么样的行为呢?这个也留给大家自行验证。但是在一般情况下,我们应该避免混用它们,否则会造成代码检查或者调试的时候难以跟踪this的值的问题。
当方法失去主语的时候,this不再有?
其实大家可以发现我的用词,当一个function被调用的时候是有主语的时候,它是一个方法;当一个function被调用的时候是没有主语的时候,它是一个函数。当一个函数运行的时候,它虽然没有主语,但是它的this的值会是全局对象。在浏览器里,那就是window。当然了,前提是函数没有被bind过,也不是被apply或call所调用。
那么function作为函数的情景有哪些呢?
首先,全局函数的调用就是最简单的一种。
function bar() {
console.log(this === window); // 输出:true
}
bar();
立即调用的函数表达式(IIFE,Immediately-Invoked Function Expression)也是没有主语的,所以它被调用的时候this也是全局对象。
(function() {
console.log(this === window); // 输出:true
})();
在线演示(包含上面两个例子)
但是,当函数被执行在严格模式(strict-mode)下的时候,函数的调用时的this就是undefined了。这是很值得注意的一点。
function bar() {
'use strict';
console.log('Case 2 ' + String(this === undefined)); // 输出:undefined
}
bar();
不可见的调用
有时候,你没有办法看到你定义的函数是怎么被调用的。因此,你就没有办法知道它的主语。下面是一个用jQuery添加事件监听器的例子。
window.val = 'window val';
var obj = {
val: 'obj val',
foo: function() {
$('#text').bind('click', function() {
console.log(this.val);
});
}
};
obj.foo();
在线演示
在事件的回调函数(第6行开始定义的匿名函数)里面,this的值既不是window,又不是obj,而是页面上id为text的HTML元素。
var obj = {
foo: function() {
$('#text').bind('click', function() {
console.log(this === document.getElementById('text')); // 输出:true
});
}
};
obj.foo();
在线演示
这是因为匿名函数是被jQuery内部调用的,我们不知道它调用的时候的主语是什么,或者是否被bind等函数修改过this的值。所以,当你将匿名函数交给程序的其他部分调用的时候,需要格外地谨慎。
如果我们想要在上面的回调函数里面使用obj的val值,除了直接写obj.val之外,还可以在foo方法中用一个新的变量that来保存foo运行时this的值。这样说有些绕口,我们看下例子便知。
window.val = 'window val';
var obj = {
val: 'obj val',
foo: function() {
var that = this; // 保存this的引用到that,这里的this实际上就是obj
$('#text').bind('click', function() {
console.log(that.val); // 输出:obj val
});
}
};
obj.foo();
在线演示
另外一种方法就是为该匿名函数bind了。
window.val = 'window val';
var obj = {
val: 'obj val',
foo: function() {
$('#text').bind('click', function() {
console.log(this.val); // 输出:obj val
}.bind(this));
}
};
obj.foo();
发表评论
-
微信开发工具中时间问题的小坑
2018-02-07 19:07 827刚开始用微信小程序开发工具,每次运行任何应用,都报这个错误: ... -
三篇不错的介绍CSS GRID的文章
2017-12-06 09:08 555三篇不错的介绍CSS GRID的文章: http://www. ... -
双因素认证(2FA)教程
2017-11-03 09:16 1572http://www.ruanyifeng.com/blog/ ... -
es6 中的export
2017-08-20 08:00 824https://juejin.im/post/5998625f ... -
markdown中的空格
2017-08-20 07:53 1704即使手动输入空格, 也是很不推荐的方法。我推荐全角空格,切换 ... -
(转)讲真,别再使用JWT了
2017-08-17 23:21 1013不错的好文: http://insights.thoughtw ... -
(转)手把手教你WebStorm+chrome实现时时调试刷新
2017-08-15 10:50 3030参考: http://jingyan.baidu.com/ar ... -
IntelliJ Idea 2017 免费激活方法
2017-08-15 09:38 93351. 到网站 http://idea.lanyus.com/ ... -
前端框架这么多,该何去何从?
2017-08-04 07:17 650http://insights.thoughtworkers. ... -
记录一个HTML 5画拓扑图的商业公司
2017-07-18 19:56 850http://qunee.com/ DEMO:http:// ... -
vue 2例子学习收集
2017-07-16 11:46 10091 vue2.0手撸闲鱼App https://githu ... -
(收藏)虚拟DOM内部是如何工作的
2017-07-13 22:08 596虚拟DOM内部是如何工作的 https://segmentfa ... -
最近看到的几篇精彩JAVASCRIPT博客文章推荐
2017-07-11 07:10 572【深度长文】JavaScript数组所有API全解密 http ... -
jsonp 跨域原理:深入浅出 jsonp
2017-07-10 19:55 1432https://lzw.me/a/jsonp.html jso ... -
(转)深度长文-JavaScript数组所有API全解密
2017-07-08 19:59 824深度长文-JavaScript数组所有API全解密 http: ... -
(收藏)网页导出PDF的方案
2017-07-06 07:13 988(收藏)网页导出PDF的方案 https://yiqiwuli ... -
Chromium 新的弹窗机制以及 HTML 的 <dialog> 元素
2017-06-28 12:37 1151https://juejin.im/post/59525195 ... -
国内一个不错的大屏UI设计厂家
2017-06-03 19:43 3160http://www.lanlanwork.com/dp.ph ... -
canvas仿芝麻信用分仪表盘
2017-05-28 20:21 1594canvas仿芝麻信用分仪表盘 https://segment ... -
(转)CSS 变量教程
2017-05-10 21:12 580http://www.ruanyifeng.com/blog/ ...
相关推荐
理解面向对象编程的基本原理,以及如何在JavaScript中有效地使用这些原则,对于构建高效、可维护的应用程序至关重要。同时,建立健全的测试机制也是开发高质量JavaScript代码不可或缺的一部分。
通过阅读《You Don't Know JS》中文版,开发者能够深入理解JavaScript的本质,避免常见的陷阱,并提升编写高质量JavaScript代码的能力。无论你是初学者还是经验丰富的开发者,这套书籍都将是你提升JavaScript技能的...
第五章涉及声明和访问控制,涵盖了数组的使用、访问修饰符的作用,以及this关键字、构造器和方法的区别,这些都是编写Java程序时必不可少的知识。第六章提到了流程控制、异常处理和断言,这些都是编写复杂程序时不可...
在学习JavaScript时,理解原型链、闭包、作用域以及this关键字的用法是必不可少的。同时,熟悉ES6及以后的新特性,如箭头函数、模板字符串、解构赋值、let和const等,能帮助开发者写出更简洁、高效的代码。 对于...
- **知识点详情**:题目中的正确选项包括了使用this关键字调用构造方法的一些规则:使用this调用构造方法的格式为`this([参数1, 参数2...])`;只能在构造方法中使用this调用其他构造方法;使用this调用其他构造方法...
理解如何创建和访问对象属性(点表示法和方括号表示法),以及如何使用`this`关键字是重要的。 6. **事件和DOM操作**:在前端开发中,JavaScript常常用于响应用户在网页上的操作,比如点击按钮。这涉及到DOM(文档...
1. 变量:在JavaScript中,我们使用`var`、`let`或`const`关键字声明变量。例如: ```javascript let num = 123; const pi = 3.14; ``` `num`可以被重新赋值,而`pi`是常量,一旦赋值不可更改。 2. 数据类型:...
在IT行业中,JavaScript是一种广泛使用的编程语言,尤其在前端开发领域。标题"ecma-angular:ecma6 角度概念验证"表明我们将讨论的是关于ECMAScript 6(也称为ES6)在Angular框架中的应用。Angular是一款由Google维护...
在这个活动中,学生可能会学习如何使用JavaScript创建类,定义构造函数、属性和方法,理解this关键字的作用,以及如何通过.prototype进行继承。此外,他们还会接触到HTML5 Canvas API,学习如何创建canvas元素,获取...
【标题】:深入理解JavaScript(基于st-master项目) 在JavaScript的世界里,"st"可能指的是一个特定的项目或库,但在这个场景下,由于提供的信息有限,我们将从更广泛的角度来探讨JavaScript的核心概念和相关技术...
3. 高级特性:如闭包、原型链、作用域、this关键字、异步编程(Promise、async/await)等,这些在复杂问题中尤为重要。 二、算法基础 在LeetCode中,算法是解决问题的关键。以下是一些常见的算法类型及其在...
在IT行业中,JavaScript是一种广泛使用的编程语言,尤其在Web开发领域。它以其灵活性、动态性和丰富的库支持而闻名。在“Angry Birds Stage 2.5”这个项目中,我们看到JavaScript被应用于创建一个游戏阶段,这可能是...
作用域是任何编程语言中至关重要的概念,它决定了变量和函数的可访问范围。在JavaScript(JS)中,作用域尤为复杂且容易让人困惑。本文将从JS运行机制的角度来探讨作用域的形成机制、块级作用域、声明提升机制等核心...
在ES6之前,JavaScript使用原型链实现面向对象编程,但随着ES6的引入,我们有了更接近传统面向类的语言特性。通过`class`关键字,我们可以定义类,而`extends`关键字则用于实现类的继承。例如,我们可以定义一个基础...
作者站在普通网页设计人员的角度,用平实生动的语言,向您讲述XML的方方面面,帮助你拨开XML的神秘面纱,快速步入XML的新领域。 • 第一章:XML快速入门 • 一. 什么是XML? • 二. XML是新概念吗? • 三. 使用...
在JavaScript ES6中,我们可以通过`class`关键字来定义类,并使用`extends`关键字来实现继承。例如: ```javascript class Bird { constructor(weight) { this.weight = weight; } fly() { console.log('小鸟...
本篇将深入探讨这些知识点,并结合JavaScript语言进行详细阐述。 首先,我们来理解“类继承”这一概念。在面向对象编程(OOP)中,类是创建对象的蓝图,它定义了对象的属性和方法。类继承则是从已有的类(称为父类...
在本项目"Angry Birds Stage...通过分析和修改这些代码,学生能够更好地理解JavaScript的类继承和图像处理,并实际应用到游戏开发中。这是一个将理论与实践相结合的优秀教学案例,有助于提升学生的编程技能和创新能力。
在本课程"第27课"中,我们将深入探讨JavaScript编程的一个关键概念——类继承,以及如何结合图像处理来...通过对这些代码的分析和学习,我们可以更好地理解JavaScript中的类继承以及如何结合图像处理技术创建互动游戏。
在本项目"Angry Birds Stage 2.5"中,我们关注的是利用JavaScript编程语言来实现一个基于愤怒小鸟游戏的教育活动,特别是涉及到类继承和图像处理的知识点。以下是关于这些主题的详细解释: **类继承(Class ...