看完这篇文章,你将了解
- keydown 和 keypress 的区别
- onblur 事件是什么,怎么用
- readonly 属性是什么
- 从一道题目进一步认识 prototype
- 双重循环可以用哈希表优化
- JavaScript 如何实现链表
keydown 和 keypress 的区别
- keydown 和 keyup 配对,响应所有键盘按下,全键盘除了 fn 键都可以;keydown 的时候按住会持续触发
- keypress 响应字母键盘输入,包括 a-z, 0-9 和符号键;响应按下或按住,按住的时候会持续触发
onblur 事件当一个元素失去焦点时会触发
- onblur = fn 或者 addEventListener('blur', fn) 调用
- 注意:onblur 是元素失去焦点,onfocus 是元素获得焦点
- demo
readonly 属性
If set to
true
, then the user cannot change the value of the element. However, the value may still be modified by a script.- 可以用于 input 标签:A Boolean attribute which, if true, indicates that the input cannot be edited
- readonly 只对 input 和 textarea 有效,而 disable 对所有表单元素有效
prototype 解析
看一个问题:
var A = {n: 4399}
var B = function() {this.n = 9999}
var C = function() {var n = 8888}
B.prototype = A
C.prototype = A
var b = new B()
var c = new C()
A.n++
// b.n === ?
// c.n === ?
解决的关键是要清楚:
- 如果一个对象,自身属性和 proto 引用有相同属性,那么以自身属性优先
先找自己身上有没有该属性,找不到,再进入原型链搜索
new 的本质是让函数返回一个对象的语法糖,它干了这几件事
function xx() { let obj = {} let this = obj ... // 原代码 return obj }
所以 var n = 8888
不同于 this.n = 8888
,不能让生成的对象具有属性 n
双重循环用哈希表优化
形如
for(let i=0; i<nums[i].length; i++) {
for(let j=0; j<nums[j].length; j++) {
}
}
的代码结构,有时可以用哈希表取代遍历,将两层遍历转化为两次遍历
比如:
我一开始是这样
var twoSum = function(nums, target) {
for(let i=0; i<nums.length; i++) {
for(let j=i+1; j<nums.length; j++) {
if(nums[i] + nums[j] === target) {
return [i, j]
}
}
}
};
优化后时间减半
var twoSum = function(nums, target) {
// 遍历第一次,用哈希表记下 {数组值, 下标}
let hash={}
for(let i=0; i<nums.length; i++) {
let value = i
let key = nums[i]
hash[key] = value
}
// 遍历第二次,根据差值找哈希表中是否答案
for(let i=0; i<nums.length; i++) {
let another = target - nums[i]
let j = hash[another]
if(j !== undefined && j !== i) {
return [i, j]
}
}
};
JavaScript 如何实现链表
定义链表
function ListNode(val) {
this.val = val;
this.next = null;
}
可以用头结点的技巧新建链表
一开始没用头结点,导致代码比标准答案冗长。按照答案修改后又总是出 bug,后来细心观察才发现它用到了头结点的技巧。套路如下:
let l3 = new ListNode(null)
let k = l3
...
k.next = new ListNode(xx)
k = k.next
...
return l3.next // 注意这里
这里是demo
暂无评论