// 声明全局变量 - 全局作用域
var msg = 100;
// 声明局部变量 - 某个函数作用域
function fn() {
// 局部变量 - 只能在当前函数作用域中访问
var msg2 = 200;
console.log(msg2,msg);
}
fn()
console.log(msg)
// 先调用后声明
console.log(msg); //打印undefined
var msg = 100;
console.log(msg); //打印100
以上代码会先输出undefined
然后输出100
。约等于以下写法
var msg;
console.log(msg);
msg=100;
console.log(msg);
所以变量提升也就是变量的声明被提升了
即使我们在定义这个函数之前调用它,函数仍然可以工作。这是因为在 JavaScript 中执行上下文的工作方式造成的。
JavaScript 仅提升声明,而不提升初始化。如果你先使用的变量,再声明并初始化它,变量的值将是 undefined
。变量提升也会在函数内产生,例如
var msg = 100;
function fn() {
console.log(msg); //undefined
var msg = 200;
console.log(msg); //200
}
fn();
console.log(msg); // 100
因此我们可以得到结论:全局变量与局部变量同名时,在函数作用域中只能访问局部变量
函数提升与变量提升较为类似。函数声明时 函数可以被正确被调用
fn(); //输出 this is function
function fn() {
console.log("this is function");
}
fn(); // 输出 this is function
如果表达式方式声明存在的函数提升是按照变量提升,因此函数不能被正确调用。
fn();
var fn = function () {
console.log("this is function");
};
fn();
// 报错:TypeError: fn is not a function
函数声明方式时 函数提升比变量提升的优先级更高。
console.log(fn); //打印函数fn:[Function: fn]
var fn = 100;
function fn() {
console.log("this is function");
}
JavaScript
中只有一个复杂数据类型那就是object
,它既是一个函数也是一个构造函数。
创建对象有三种方式,分别为:
var obj = {
name: "李磊",
age: "18",
sayMe: function () {
console.log("Hello World");
},
};
创建一个空对象
var obj1 = {};
var obj = new Object();
obj.name = "李雷";
obj.sayMe = function () {
console.log("this is lilei.");
};
创建一个空对象
var obj2 = new Object();
var obj = Object.create(null);
obj.name = "李雷";
obj.sayMe = function () {
console.log("this is lilei.");
};
创建一个空对象
var obj3 = Object.create(null);
var car = {}
car.name = 'ford' //通过点符号为该对象新增属性
car['year'] = 1984 //通过方括号为该对象新增属性
console.log(car)
Object.hasOwnProperty()
方法来判断对象的属性是否存在var obj = {
name: "test",
age: 123,
};
if (obj.msg === undefined) {
console.log("与undefined比较");
}
if (!obj.msg) {
console.log("if判断");
}
console.log("in运算符判断", "msg" in obj);
console.log("hasOwnProperty判断", obj.hasOwnProperty("msg"));
以上代码输出结果为:
与undefined比较 if判断 in运算符判断 false hasOwnProperty判断 false
构造函数分为三种,不接受参数的构造函数、接受参数的构造函数与使用属性的构造函数。
function Hero() {
// 属性
this.name = "李雷";
// 方法
this.sayMe = function () {
console.log("this is lilei.");
};
}
function Hero(name) {
// 属性
this.name = name;
// 方法
this.sayMe = function () {
console.log("this is lilei.");
};
}
function Hero(name) {
// 属性
this.name = name;
// 方法
this.sayMe = function () {
console.log("this is " + this.name + ".");
};
}
在构造函数中的this
表示的是初始化的对象。例如声明一个Hero
类型的变量,调用是就可以看到编辑器提示的属性了。
var hero = new Hero("lilei");
console.log(hero.name); //打印lilei
简单来说就是为某个属性设置为函数。
function Score() {
// 当做函数使用 -> 定义局部变量(初始化默认值)
var score = 100;
// 当做构造函数使用
this.getter = function () {
return score;
};
this.setter = function (new_value) {
score = new_value;
};
}
var result = new Score();
console.log(result.getter()); // 100
result.setter(200);
console.log(result.getter()); // 200
因为setter
与getter
都被赋予了函数,因此被称为方法,调用时也自然要加上小括号了。
简单来说就是将属性写在对象里,方法写在对象的return
里。
function Score() {
// 局部变量
var score = 100;
// 返回一个对象
return {
getter: function () {
return score;
},
setter: function (new_value) {
score = new_value;
},
};
}
var result = Score();
console.log(result.getter()); // 100
result.setter(200);
console.log(result.getter()); // 200
删除对象使用delete
运算符,删除后再次访问则会显示undefined
var user = {
name: '李雷',
age: 18
}
delete user.age
console.log(user) //undefined
遍历对象毫无疑问用的是for-in
迭代。这样迭代过程中判断是否是方法可以使用instanceof
var obj = {
name: "李雷", // string
age: 18, // number
sayMe: function () {
console.log("我是李雷.");
},
};
for (attr in obj) {
// 如何区分属性和方法?
if (obj[attr] instanceof Function) {
console.log("说明当前这个是方法");
} else {
console.log("说明当前这个是属性");
}
}