1. 考察this
1.1
var name = 'naruto';
function show() {
console.log('this:', this.name);
}
var obj = {
name: 'xiaowa'
show: show
}
obj.show(); // this: xiaowa
当obj调用show()时,show的this被隐私绑定到调用它的obj上,所以在show里面可以拿到obj的name属性
var name = 'naruto';
function show() {
console.log('this name:', this.name)
}
var obj = {
name: 'xiaowa',
show: function() {
show();
}
}
obj.show(); // this: naruto
// 或者
var name = 'naruto';
function show() {
console.log('this name:', this.name)
}
var obj = {
name: 'xiaowa',
show: show
}
var newShow = obj.show;
newShow(); // this: naruto
虽然obj声明了show属性并定义一个function,但是执行的时候是在全局作用域中直接执行,show函数中的this执行window;
1.2
var name = 'naruto';
var obj1 = {
name: 'xiaowa',
show: function() {
console.log('this name:', this.name)
}
}
(0, obj1.show)(); // this name: xiaowa
其实还是obj调用show方法,this指向obj;
(1,2,3, function(){console.log('我是最后一个执行')})() // 我是最后一个执行
1.3
var obj = {
name: 'naruto',
sub: function() {
name: 'xiaowa',
show: function() {
console.log('this name:', this.name)
}
}
}
obj.sub.show(); // this name: xiaowa
这种情况的调用位置在sub对象里,在show被调用时,this指向sub;
1.4
var name = 'naruto';
var obj = {
name: 'xiaowa',
show: function() {
this.name = 'func';
console.log('this name:', this.name)
}
}
var newObj = new obj.show(); // this name: func
newObj 是通过new构造出来的一个实例对象,这个新对象指向obj.show的原型
1.5
var name = 'naruto';
var obj = {
name: 'xiaowa',
show: function() {
this.name = 'func';
console.log('this name:', this.name);
}
}
var newObj = new (obj.show.bind(obj))(); // this name: func
绑定优先级问题: new > 显示绑定(bind > call & apply) > 隐式绑定
1.6
var obj = {
show: function() {
console.log('this :', this)
}
};
var elem = document.getElementById('create');
elem.addEventListener('click', obj.show); // 返回elem dom对象
elem.addEventListener('click', obj.show.bind(obj)); // obj
elem.addEventListener('click', function() {
obj.show(); // obj
});
elem.addEventListener('click', obj.show);
点击elem监听click事件属于方法调用,其中的this指向DOM对象;
elem.addEventListener('click', obj.show.bind(obj));
bind强绑定到obj上;
elem.addEventListener('click', function() obj.show();});
,this三板斧中,谁点谁就指向谁;
2. 作用域
2.1
var person = 1;
function showPerson() {
var person = 2;
console.log(person);
}
showPerson(); //2
函数作用域,在执行showPerson时,在自身作用域空间中定义了person,因为console为2;
2.2
var person = 1;
function showPerson() {
console.log(person);
var person = 2;
}
showPerson(); //undefined
主要考察变量提升,在函数作用域中,person变量会提升,在打印时已定义未赋值,为undefined;
2.3
var person = 1;
function showPerson() {
console.log(person);
var person = 2;
function person() {};
}
showPerson(); // ƒ person() {}
函数提升优先于变量提升
2.4
var person = 1;
function showPerson() {
console.log(person);
function person() {};
var person = 2;
}
showPerson(); // ƒ person() {}
还是提升优先级问题,同2.3
2.5
for(var i = 1; i < 10; i++) {
console.log(i)
} // 1 2 3 4 5 6 7 8 9
for(var i = 1; i < 10; i++) {
setTimeout(function() {
console.log(i)
})
} // 10 10 10 10 10 10 10 10 10
// 回调函数在循环结束后执行
for(var i = 1; i < 10; i++) {
(function(i) {
setTimeout(function() {
console.log(i)
})
})(i)
} // 1 2 3 4 5 6 7 8 9
// 通过自执行函数创建的作用域,把i传入自执行函数的作用域中,每次IIFE都创建一个新的作用域,在每次循环时都有一个新的变量供我们访问
for(let i = 1; i < 10; i++) {
setTimeout(function() {
console.log(i)
})
} // 1 2 3 4 5 6 7 8 9
// let 声明还会有一个特殊的行为。这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明。随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。
3. 面向对象
3.1
function Person() {
this.name = 1;
return {}
}
var person = new Person();
console.log('name :', person.name) // naem : undefined
构造函数中return空对象,在person实例中获取name的属性为undefined
3.2
function Person() {
this.name = 1;
}
Person.prototype = {
show: function() {
console.log('name is:', this.name);
}
}
var person = new Person();
person.show(); // name is: 1
原型继承,在构造函数创建出来的对象里,会通过__proto__查找构造器中的原型, person.__proto__ === Person.prototype
3.3
function Person() {
this.name = 1;
}
Person.prototype = {
name: 2,
show: function() {
console.log('name is:', this.name);
}
}
var person = new Person();
person.show(); // name is: 1
Person.prototype.show = function() {
console.log('new show')
}
person.show(); // new show
考察原型链,如果在实例中找到了则返回,如果没有找到就会在当前实例中的原型对象里查找; Person.prototype.show覆盖了上面原型对象中的show
3.4
function Person() {
this.name = 1;
}
Person.prototype = {
name: 2,
show: function() {
console.log('name is:', this.name);
}
}
var person = new Person();
var person2 = new Person();
person.show = function() {
console.log('new show');
}
person.show();// new show
person2.show(); // name is: 1
原型链
3.5
function Person() {
this.name = 1;
}
Person.prototype = {
name: 2,
show: function() {
console.log('name is:', this.name)
}
}
Person.prototype.show();
(new Person()).show();
Person 原型对象中定义了name:2,在通过prototype获取name值为2;
new 方法创建新对象,调用show时,此时还是原型链查找