onclick 属于 dom 的 Level 0 标准
普通情况下:输出最后一个 onclick 事件 。
// 只弹出 hehe
bt.onclick = () => {
alert('haha')
}
bt.onclick = () => {
alert('hehe')
}
高级事件绑定:addEventListener
addEventListener 属于 dom 的 Level 2 标准
注意细节:
btn.addEventListener('click',function () {
alert(this.value) // this 指向 btn
}) // 第三个参数代表捕捉,还是冒泡
// 先 haha ,再 hehe
btn.addEventListener('click',function () {
alert('haha')
})
btn.addEventListener('click',function () {
alert('hehe')
})
addEventListener:第三个参数代表捕捉还是冒泡,默认值是false,冒泡
问题:点击hd,先输出哪个?
// 输出顺序: b-china, b-bj,b-hd,m-hd,m-bj,m-china
china.addEventListener('click',function () {
alert('b-china')
}, true)
bj.addEventListener('click', function () {
alert('b-bj')
}, true)
hd.addEventListener('click', function () {
alert('b-hd')
}, true)
china.addEventListener('click', function () {
alert('m-china')
}, false)
bj.addEventListener('click', function () {
alert('m-bj')
}, false)
hd.addEventListener('click', function () {
alert('m-hd')
}, false)
停止传播:stopPropation
阻止事件默认行为:preventDefault
// 阻止捕捉
hd.addEventListener('click', function (ev) {
alert('b-hd')
ev.stopPropation()
}, true)
// 阻止冒泡
hd.addEventListener('click', function (ev) {
alert('b-hd')
ev.stopPropation()
},false)
问题:为什么在函数里面 return false 不能停止传播?
答:该函数没有返回值。
不声明变量,容易污染全局变量
// 第一种情况
function t() {
e = 6
}
t()
console.log(e) // 6
// 第二种情况
e =1
function t() {
e = 6
}
t()
console.log(e) // 6
// 第三种情况
e =1
function t() {
var e = 6
}
t()
console.log(e) // 1
变量提升顺序: 参数,var 声明,函数声明
// 输出5
function t(age) {
var age = 5
console.log(age)
}
t(99) // 5
// 输出函数
function t(greet) {
console.log(greet) // funtion
function greet() {
console.log(greet) // funtion
}
greet()
}
t(3) // function
t1() // 1
t2() // undfined
function t1() { // 函数声明
console.log(1)
}
var t2 = function () { // 函数表达式
console.log(2)
}
arguments: 长的像数组的对象
function t(){
console.log(arguments) // 实参
console.log(arguments.callee) // 指向srfunction t()
}
t(1) // [1],形参
t(1, 2) // [1, 2]
t(1, 2, 3) // [1, 2, 3]
问题:用递归来做 1,2,3...100 的和?
// 普通解决方案:
function sum(n) {
if (n > 1) {
return n + sum(n - 1)
} else {
return 1
}
}
console.log(sum(100))
// 用arguments
var rs = (function (n) {
if (n > 1) {
return n + arguments.callee(n - 1)
} else {
return 1
}
})(100)
console.log(rs)
哪个对象调用,this 指向谁
详情请看:js基础面试准备内容=>https://juejin.im/post/5bdae583e51d457c37113414
apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向)。
他们的常用用法:
验证是否是数组(前提是toString()方法没有被重写过)
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]' ;
}
让类数组拥有数组的方法
比如arguments对象,获取到的文档节点等,并没有数组的那些方法:
Array.prototype.slice.apply(argument); //理论上来说这个比较快,直接在原型上查找slice方法。
[].slice.apply(arguments); //理论上来说这个比较慢,因为要Array做一个实例化再查找slice方法,实际上比较快,因为现在的各种自动化工具会把上一种方法转换为这种。
var name = '11'
var obj = {
name:'22',
getName:function(){
return function(){
return this.name
}
}
}
console.log(obj.getName()()) // 11
// 函数闭包
function t(){
var age = 21;
return function () {
console.log(age++) // 21
}
}
var tmp = t()
var age = 1000
tmp()
// 闭包计数器
var cnt = (function(){
var n=1;
return function(){
return n++
}
})()
console.log(cnt()) // 1
console.log(cnt()) // 2
console.log(cnt()) // 3
用闭包来完成js面向对象之私有属性
var Person = function() {
var data = {
name: 'es3',
sex: 'male',
age: 15
}
this.get = function(key) {
return data[key]
}
this.set = function(key, value) {
if (key != 'sex') {
data[key] = value
}
}
}
原型继承:prototype实现,父亲是_proto__,详情看=>js基础面试准备内容。
特点:简单易懂,但是无法实现多继承,父类新增原型方法/原型属性,子类都能访问到。
原型冒充:call方法
function Good() {
this.study = function(){
console.log('高效学习')
}
}
function Bad() {
Good.call(this) // 原型冒充
this.play = function() {
console.log('王者荣耀')
}
}
var bad = new Bad()
bad.study()
特点:可以实现多继承,但是只能继承父类的实例属性和方法,不能继承原型属性/方法。
复制继承:
function Good() {
this.study = function(){
console.log('高效学习')
}
}
function Bad() {
this.play = function() {
console.log('王者荣耀')
}
this.extend = function(obj) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
this[key] = obj[key];
}
}
}
}
var bad = new Bad()
bad.extend(new Good())
bad.study()
var t = function (a,b,c) {
}
console.log(t.length) // 3 length代表函数的形参数量
console.log(t.name) // t name 函数名
方法如下;
问题:
instanceof:如果__proto__发生改变,会失效
var arr = [1, 2, 3 ]
arr.__proto__=Object.prototype
arr instanceof Array // false