【九】JavaScript之对象
【1】对象
- js中,虽然是函数优先的编程语言,但是使用上也是基于对象的
- 所以在js中也存在万物皆为对象的情况。
【2】对象的创建
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
/**
* 对象的创建
*/
// 1. 通过字面量{}创建
var xiaoming1 = {}; // 空对象
var xiaoming2 = { // 有属性有方法的对象
age: 18,
sex: true,
desc(){
console.log("js对象的方法");
console.log(this.age, this.sex); // this表示当前对象
}
}
console.log(xiaoming1);
console.log(xiaoming2);
// 对象的属性调用
console.log(xiaoming2.age)
// 对象的方法调用
xiaoming2.desc()
// 2. 通过系统对象Object来创建
var xiaoming3 = new Object(); // 空对象
var xiaoming4 = Object(); // 空对象
// Object是javascript提供给开发者创建空对象使用的.
// Object内部基本都是一些不对外开放的方法属性
// Object是javascript内部的一切对象的基本对象[构造函数]
console.log(xiaoming3);
console.log(xiaoming4);
// 3. 通过构造函数来创建对象
function Humen(name="匿名对象",age=0){
this.name = name;
this.age = age;
this.say = function(){
console.log("我是Humen里面的代码");
}
}
var xiaoming5 = new Humen("小明", 17);
console.log(xiaoming5);
//4. 通过类创建对象
// 类名 后面必须跟着花括号,花括号内部就是类里面的代码
// 原生js中的类只存在实例方法或实例属性,没有类属性或类方法
class Person{
// 构造函数,方法名必须叫constructor,等同于 python的类中的__init__方法
constructor(name, age) {
this.name = name;
// 等同于python里面的 self.age = age
this.age = age;
}
say(){
// 对象的方法,将来在类被实例化的时候,可以让对象调用
console.log(`我叫${this.name},我今年${this.age}岁!`)
}
}
var xiaoming6 = new Person("小明",18)
xiaoming6.say();
</script>
</body>
</html>
【3】对象的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var xiaoming = { // 有属性有方法的对象
age: 18,
sex: true,
desc(){
console.log("js对象");
}
}
// 可以给对象追加新属性或新方法,也可以针对原有的属性值或方法进行修改
xiaoming.name = "小明";
// 给对象追加方法,在对象的外部,追加方法,不能使用箭头函数
xiaoming.say = function(){
console.log(`我叫${this.name},我今年${this.age}岁!`);
}
console.log(xiaoming);
// 访问对象的属性
console.log(xiaoming.name);
console.log(xiaoming.age);
// 访问对象的方法
xiaoming.say();
</script>
</body>
</html>
【4】this伪对象
- 默认情况下,在对象的方法中,this代表的就是当前对象
- 在函数或者函数外界,this代表的是当前页面的超全局对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// 在函数外界,this就是window对象
// console.log(this);
// console.log(window);
// console.log(this === window);
// // 在对象的方法中,this代表的就是当前对象
// class Humen{
// constructor(name, age) {
// this.name = name;
// this.age = age;
// }
// say(){
// return `你好,我叫${this.name}!`
// }
// }
//
// var xiaohong = new Humen("小红", 18);
// console.log(xiaohong);
// console.log( xiaohong.say() ); // // say是xiaohong的方法,所以this代表小红
//
// var xiaoming = new Humen("小明", 13);
// console.log(xiaoming);
// console.log( xiaoming.say() ); // // say是xiaoming的方法,所以this代表小明
// 所以要看清楚,方法或函数在调用时,左边的变量是谁?
var name = "window下的变量";
function desc(){
return this.name;
}
class Company{
constructor(name) {
this.name = name;
}
}
var c = new Company("小明科技有限科技公司")
c.desc = desc;
console.log(c.desc()); // 小明科技有限科技公司
class Person{
constructor(name) {
this.name = name;
}
}
var p = new Person("张三丰");
p.desc = desc;
console.log( p.desc() ); // 张三丰
console.log(p.desc === c.desc); // true
// 请问这里会显示什么呢?
console.log( desc() ); // desc调用时左边时没有任何的变量的,所以默认是window调用,因此在desc函数中,this代表的就是window对象
</script>
</body>
</html>
【5】函数或方法与作用域的问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// // js属于解释器语言,所以针对代码的运行实际上分了2个阶段:词法解析 与 代码执行。
// // 普通函数与匿名函数除了在代码的运行阶段上分配空间的时间不一样以外,其他的操作都是一样的。
// // 普通函数分配空间是在词法解析阶段分配的。
// // 匿名函数分配空间是在代码执行阶段分配的。
// function abc(){
// console.log("hello")
// }
// var func = abc // 在js中实际上分2部执行的, 词法解析阶段先执行 var func; 代码执行阶段后执行 func = abc;
// func();
// abc();
//
//
// // 箭头函数实际上并不是匿名函数的简写,而是一种特殊的匿名函数。
// // 箭头函数分配空间也是在代码执行阶段分配的。
// let fn = (a,b) => { // 箭头函数的参数列表,在只有一个形参的情况下, let fn = a => {}
// return a+b
// }
// console.log( fn(10,20) );
//
// // 简写效果:
// let fn2 = (a,b) => a+b; // 如果箭头函数的代码段中只有一行代码,可以省略return
// console.log( fn2(10,20) );
// // 三种函数实际上都可以作为函数的参数使用,在这种情况下,实际上就会存在一些细微的区别。
// var arr1 = ['a', '1', '10', '102', 11,51,31,32,33,40, 'w', 'c']
// // 1. 把普通函数作为参数传递
// function fn(a,b){
// return a-b // 正序
// // return b-a // 倒序
// }
//
// // 数组排序,按数字大小排序,忽略字母
// arr1.sort(fn)
// console.log(arr1);
// // 2. 把普通匿名函数作为参数传递
// var arr1 = ['a', '1', '10', '102', 11,51,31,32,33,40, 'w', 'c']
// arr1.sort(function(a, b){
// // return a-b;
// return b-a;
// })
// console.log(arr1)
// // 3. 把箭头函数作为参数传递
// var arr1 = ['a', '1', '10', '102', 11,51,31,32,33,40, 'w', 'c']
// arr1.sort((a, b)=>a-b); // 正序
// // arr1.sort((a, b)=>b-a); // 倒序
// console.log(arr1)
/**
* 箭头函数与匿名函数的区别
*/
// // 案例1:
// class Bloom{
// constructor(time) {
// this.time = time;
// this.t = null;
// }
// has_time(){
// // 倒计时功能
// if(this.time>0){
// clearInterval(this.t);
// // this.t = setInterval(function(){ // 匿名函数中,this代表的window,当前匿名函数实际上是被setInterval调用的,而setInterval实际上时window对象提供的,所以this代表的window对象
// this.t = setInterval(()=>{ // 箭头函数中,this.代表的是Bloom的实例对象,箭头函数会复刻父级作用域下的this
// console.log(`this.time=${this.time}`, this);
// this.time = this.time - 1;
// if(this.time < 1){
// console.log("爆炸!!!");
// }
// }, 1000);
// }
// }
// }
//
// var b = new Bloom(3600)
// b.has_time()
// // 案例2:
// var xiaoming = {
// age: 18,
// name: "小明",
// }
//
// // xiaoming.say = ()=>{ // 使用箭头函数,箭头函数会把父级作用域下的this复刻到函数内部,则this指向window对象 ===> 我叫,我今年undefined岁!
// xiaoming.say = function(){ // 使用匿名函数,会把this指向调用当前方法的对象,则this当前对象 ===> 我叫小明,我今年18岁!
// console.log('this=',this);
// console.log(`我叫${this.name},我今年${this.age}岁!`);
// }
// console.log(xiaoming);
// xiaoming.say();
/**
* 箭头函数与匿名函数在作用域上表现不同。
* 匿名函数,会this指向到调用当前方法的对象,
* 箭头函数,会把this指向到父级作用域上的this。
*/
// js中的作用域分全局作用域与局部作用域。
// 其中,函数外就属于全局作用域,而函数内就属于局部作用域。
// 全局作用域下的变量,可以在任意位置上使用,叫全局变量,一旦定义以后,直到当前网页代码执行结束以后才会被浏览器回收。
// 局部作用域下的变量,只能在当前函数中使用,叫局部变量,在函数运行时创建,函数运行结束以后被浏览器回收,下一次函数被调用,则会被再次创建。
/**
* 全局变量具有穿透性,可以直接在函数内部调用或修改值
* @type {number}
*/
// var num = 10; // 在函数外的变量可以直接使用到函数内部
// function fn1(){
// console.log(num); // 10
// num = 20; // 对全局变量进行重新赋值
// function fn2(){
// console.log(num); // 20
// }
// fn2();
// }
// fn1();
// console.log(num); // 20
// var num = 10; // 在函数外的变量属于全局变量,但是当全局变量与局部变量一样时,函数内会优先使用局部变量
// function fn1(){
// console.log(num); // undefined
// var num = 20; // 这句代码与上面的不一样的时,多了一个var关键字
// function fn2(){
// console.log(num); // 20
// }
// fn2();
// }
// fn1();
// console.log(num); // 10
// var num = 10; // 在函数外的变量属于全局变量,但是当全局变量与局部变量一样时,函数内会优先使用局部变量
// function fn1(){
// console.log(num); // undefined
// // 这句代码与上面的不一样的是,var换成了let关键字,
// // let与var一样也是可以声明变量,但是不一样的是2点:
// // 1. let的作用域范围时花括号,var的作用域范围时函数
// // 2. 在局部作用域下,let关键字声明的变量,必须严格按照先声明后调用来执行的。
// let num = 20;
// function fn2(){
// console.log(num); // 20
// }
// fn2();
// }
// fn1();
// console.log(num); // 10
</script>
</body>
</html>
【6】全局变量与局部变量的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
/**
* js中的变量查找,是从内往外按作用域逐层查找的: 当前作用域->父级作用域->顶级作用域
* 查找过程中,如果找到则取值,停止查找流程。如果直到顶级作用域下还是没有对应的变量,则报错。
* 注意:js中,函数名、类名、变量名都是变量,最终在内存中存储的方式都是函数。
*
*
*/
// var num = 0;
// // 全局作用域[顶级作用域]
// function fn1(){ // fn1作用域
// console.log(num); // 查找到当前作用域下,已经存在了num,只是没有赋值,所以是undefined
// var num = 10;
// function fn2(){ // fn2作用域,fn1是fn2的父级作用域
// let num = 20;
// console.log(num);
// }
// fn2();
// }
// fn1();
// 面试题,一套非常坑人的题目
function fn1(){
// console.log(num); // 为什么31与32存在时,31行会报错呢?因为32中的num没有使用var或者let,所以在词法阶段,根本没有分配到空间,也没有创建对应的变量。
// num = 2;
function fn2(){
num = 2; // 此处num首次出现却不使用var声明时,这该变量会默认作为window对象的属性存在,js中调用window的属性或方法,是不需要写上window的。
console.log(num); // 2
}
fn2();
console.log(num); // 2
}
fn1();
console.log(num); // 2
</script>
</body>
</html>
标签:console,log,对象,JavaScript,作用域,num,var,函数
From: https://www.cnblogs.com/dream-ze/p/17525627.html