ReferenceError
use strict
模式下禁止自动或隐式地创建全局变量,所以在引擎执行 LHS 时,不会再隐式地创建一个全局变量,而是直接抛出一个 ReferenceError
。TypeError
, 而 ReferenceError
代表着在作用域查找或判断失败,TypeError
代表作用域查找成功了,但对该变量的操作不合规。var a = 2;
这段声明代码 JavaScript 引擎会将他们分为 var a
和 a = 2;
两个单独的声明来处理,第一个是在编译阶段所执行,第二个是在执行阶段所执行。for(var = 1 ; i <= 5; i++){
(function() {
var j = i;
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})();
}
// 再次改进后
for(var = 1 ; i <= 5; i++){
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}
1. 是否在 new 中调用(new 调用), this 指向新创建的对象
function Foo() {
// do something
}
let f = new Foo();
// call()
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
};
foo.call(obj); // 2
// apply()
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
var obj = {
a: 2,
};
var bar = function () {
return foo.apply(obj, arguments);
};
var b = bar(3); // 2 3
console.log(b); // 5
// bind()
function foo(something) {
this.a = something;
}
var obj1 = {};
var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2
var baz = new bar(3);
console.log(obj1.a); // 2
console.log(baz.a); // 3
// eg1:
function foo() {
console.log(this.a); // 2
}
var obj = {
a: 2,
foo: foo,
};
obj.foo();
// eg2:
function foo() {
console.log(this.a);
}
var obj2 = {
a: 42,
foo: foo,
};
var obj1 = {
a: 2,
obj2: obj2,
};
obj1.obj2.foo(); // 42
function foo() {
console.log(this.a);
}
var a = 2;
foo(); // 2
// 严格模式下的位置
function foo() {
'use strict';
console.log(this.a);
}
var a = 2;
foo(); // Type: this is undefined
function foo() {
console.log(this.a);
}
var a = 2;
(function () {
'use strict';
foo(); // 2
});
2. 箭头函数不会使用上述四条规则,而是根据当前的词法作用域来决定 this 的,箭头函数会继承外层函数的 this。
3. 注意:对于默认绑定来说,决定 this 绑定对象的并不是调用位置是否处于严格模式,而是函数体是否处于严格模式。如果函数体处于严格模式,this 会被绑定到 undefined, 否则 this 会绑定到全局对象。
4. 优先级问题
排序:显式绑定 > new 绑定 > 隐式绑定 > 默认绑定
var obj = {....}
)和构造形式(var obj = new Object()
)。两种形式的唯一区别在于文字声明可添加多个键值对,而构造形式必须逐个添加。.
操作符访问被称为属性访问,通过 []
操作符访问被称为键访问。var anotherObject = {
a: 2,
};
// 创建一个关联到 anotherObject 的对象
var myObject = Object.create(anotherObject);
for (var k in myObject) {
console.log('found: ' + k);
}
// found: a
'a' in myObject; // true
当你通过各种语法进行属性查找时都会查找[[Prototype]]链,直到找到属性或找到完整的原型链。
1. 但到哪是 [[Prototype]] 的尽头呢?
2. 如果对象中的某个属性不直接存在于某个对象上时会发生以下几种情况:
myObject.foo = 'bar';
let a = {
foo: 'atxt',
};
let c = Object.create(a);
c.foo = 'cfoo';
console.log('c ------>', c.foo); // atxt
let a = {
foo: 'atxt',
};
Object.defineProperty(a, 'foo', {
writable: false,
});
let c = Object.create(a);
c.foo = 'cfoo';
console.log('c ------>', c.foo); // atxt
let a = {
get foo() {
return this._foo_;
},
set foo(v) {
this._foo_ = 'afoo';
},
};
a.foo = 'afoo';
let c = Object.create(a);
c.foo = 'cfoo';
console.log('c ------>', c.foo); // afoo
// 把赋值[[put]] 操作存储到了另一个变量 _a_ 中,名称 _a_ 只是一种惯例,没有任何特殊行为,与其他普通属性一样。
3. 在面向类的语言中,类可以实例化多次。
4. 使用 new 调用是构造函数还是调用?
function NothingSpecial() {
console.log("Don't mind me!");
}
var a = new NothingSpecial();
// "Don't mind me!"
a; // {}
5. 在 JavaScript 中对于构造函数最准确的解释是,所有带 new 的函数调用。
6. 何为原型链?
7. 对象之间是通过 [[Prototype]] 链关联的。
•问题标注 Q:(question)
•答案标注 R:(result)
•注意事项标准:A:(attention matters)
•详情描述标注:D:(detail info)
•总结标注:S:(summary)
•分析标注:Ana:(analysis)
•提示标注:T:(tips)