什么是对象
在 JavaScript 中,对象是一组无序的相关属性和方法的集合,万物皆对象,对象是由属性和方法组成的。
为什么需要对象
保存一个值时,可以使用变量,保存多个值时,可以使用数组。
如果要保存一个人的完整信息呢?
例如,将张三的个人的信息保存在数组中的方式为:
var arr = ['张三', '男', 23];
上述例子中用数组保存数据的缺点是:数据只能通过索引值访问,开发者需要清晰的清楚所有的数据的排行才能准确地获取数
据,而当数据量庞大时,不可能做到记忆所有数据的索引值。
使用对象:
var zs = {
name: "张三", //键值对
sex: "男",
age: 23
}
键:相当于属性名
值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
var star = {
name : 'pink',
age : 18,
sex : '男',
sayHi : function(){
alert('大家好啊~');
}
};
对象的属性
访问对象的属性
对象里面的属性调用 : 对象.属性名
对象里面属性的另一种调用方式 : 对象['‘属性名’]
console.log(star.name) // 调用名字属性
console.log(star[‘name’]) // 调用名字属性
调用对象的方法
对象里面的方法调用:对象.方法名()
star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号
修改变量属性
start.age = 22
start['age'] = 23
创建空对象
var andy = new Object();
给空对象添加属性和方法
var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
alert('大家好啊~');
}
我们为什么需要构造函数
因为我们一次创建一个对象,里面很多的属性和方法是大量相同的 我们只能复制
构造函数注意事项
//1.自定义构造函数
function Person(name, age, height) {
this.name = name
this.age = age
this.height = height
}
//2.创建对象
var zs = new Person("张三",23,181);
var ls = new Person("李四",24,182);
console.log(zs.name)
console.log(ls.name)
for in
for (var 变量 in 对象名字) {
}
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
//1.自定义构造函数
function Person(name, sex, age) {
this.name = name
this.sex = sex
this.age = age
}
//2.创建对象
var zs = new Person("张三", '男', 23);
for (var key in zs) {
//console.log(key);
console.log(zs[key]);
}
删除对象的成员:属性及方法使用关键字delete
function Person(name, sex, age, eat) {
this.name = name
this.sex = sex
this.age = age
this.eat = eat
}
//创建对象
var zs = new Person("张三", '男', 23, function () { console.log('eat'); });
console.log(zs.age);
delete zs.age
console.log(zs.age);
zs.eat()
delete zs.eat //不可以加()
zs.eat()//调用失败
? 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
? 作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
? 作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,也称为函数作用域。
块作用域由 { } 包括。
在其它编程语言中(如 java、c#等),在 if 语句、循环语句中创建的变量,仅仅只能在本 if 语句、本循环语句中使用。
java有块级作用域:
if(true){
int num = 123;
system.out.print(num); // 123
}
system.out.print(num); // 报错
而与之类似的JavaScript代码,则不会报错:
Js中没有块级作用域
if(true){
var num = 123;
console.log(num); //123
}
console.log(num); //123
全局变量
function add() {
a = 3;//全局变量 一般不用
console.log(a);
}
add();//函数必须被执行起来
console.log(a);
局部变量
function add() {
var a = 3
console.log(a);
}
add()
console.log(a);//访问不到
全局变量和局部变量的区别
全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存;
局部变量:只在函数内部使用,当其所在的代码块的函数被调用执行时,会被初始化;
? 当代码被调用的函数代码块运行结束后,就会被销毁,因此更节省内存空间;
内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值 这种结构我们称为作用域链
采取就近原则
案例分析1:
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
案例分析2:
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 ?
console.log(b); //b的值 ?
}
}
}
fn1();
奇怪问题1:
console.log(num);
var num = 5;
奇怪问题2:
f1();
function f1(){
console.log('hello')
}
预解析相关概念
变量预解析
console.log(num); // 结果是多少?
var num = 10;
结果:undefined
注意:变量提升只提升声明,不提升赋值
函数预解析
fn();
function fn() {
console.log('未来可期');
}
结果:'未来可期'
注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!
提升之后:
function fn() {
console.log('未来可期');
}
fn();
匿名函数问题
匿名函数会执行变量提升,此时接收函数的变量名无法正确的调用:
fn();
var fn = function() {
console.log('未来可期');
}
结果:报错提示 ”fn is not a function"
解释:该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用
提升之后:
var fn;
fn();
fn = function () {
console.log('未来可期');
}
总结:
预解析案例:
// 案例1
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
//预解析之后------------------
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num = 10;
fun();
//案例2
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fn();
//预解析之后------------------
var num;
function fn() {
var num;
console.log(num);
num = 20;
console.log(num);
}
num = 10;
fn();
// 案例3
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
//预解析之后------------------
var a;
function f1() {
var b = 9;
var a;
console.log(a);
console.log(b);
a = '123';
}
a = 18;
f1();