11、对象、包装类

对象、包装类

对象

1.用已学的知识点,描述一下你心目中的对象。

var mrJason = {
    name : "MrJason",
    age : 40,
    sex : "male",
    health : 100,
    smoke : function () {  // 对象的属性里放函数就叫方法
        console.log('I am smoking ! cool!!!');
        this.health -- ;  
    // 不能直接写health-- 因为系统需要知道是哪个属性的health,但是一般不直接写函数名,都是用第一人称 this 比如张杰不会说:张杰很帅 只会说:我很帅 因为使用第一人称
    },
    drink : function () {  // 对象的属性里放函数就叫方法
        console.log('I am drink');
        this.health ++ ;
    },  
}

// 方法调用
mrJason.smoke 代表函数的引用
mrJason.smoke() 执行函数smoke  // 函数没有return 所以控制台打印undefined
mrJason.health  --> 99 

2.属性的增、删、改、查

var mrJason = {
    name : "MrJason",
    age : 40,
    sex : "male",
    health : 100,
    smoke : function () {
        console.log('I am smoking ! cool!!!');
        this.health -- ;  
    },
    drink : function () {
        console.log('I am drink');
        this.health ++ ;
    },
}

// 属性的增
mrJason.wife = "xiena"   // 这里需要写值,不写值就成访问了 写完之后访问mrJason就会增加这个属性,可以在控制台写 也可以在mrJason外定义

// 属性的删
delete mrJason.age   // 可以在控制台写 也可以在mrJason外写,写完属性就没了
mrJason.age  // 打印undefined 
// 访问一个不存在的对象属性不报错会打印undefined (如果是没声明的变量,打印会报错)

// 属性的改
mrJason.wife = "xiena111"   // 可以在控制台写 也可以在mrJason外写,写完属性值就改变了

// 属性的查
mrJason.wife  // 查看wife的值
console.log(mrJason.wife)  // 直接打印值也是查的方式
// 练习
var Jason = {
    prepareWife : "xiaowang",  // 未婚妻
    name : zhangjie,
    sex : "male",
    gf : "xiaoliu",
    wife : "",
    divorce : function () {
          delete this.wife,
          this.gf = this.prepareWife;
    },
    getMarried : function () {   
   // 每次结婚的时候会把girlfriend变成wife 离婚的时候把wife放到prepareWife里面去
        this.wife = this.gf,
    },
    changePrepareWife : function (someone) {  // 传参
        this.prepareWife = someone;
        // 控制台传参 Jason.changePrepareWife('xiaozhang')
    }
}
// 传参也可以写在函数外 Jason.changePrepareWife('xiaozhang')

3.对象的创建方法

字面量
// 对象的创建方法
// 1.var obj = {}  plainObject  对象字面量/对象直接量
构造函数
  1. 系统自带new Object();Array(;Number();Boolean();String0);Date();

    // 2.构造函数
    //  a. 系统自带的构造函数 : Object()、Array()、Number()等
    //	构造函数Object()基本定义:
    //	就是一个可以执行的函数,但执行函数没什么用,如果想通过函数来产生对象的话,系统自带的构造函数就相当于一个工厂,可以批量的生产对象,生产的对象完全一样又彼此独立,就像每一个工艺品一样。
    //	new Object():
    //	new 加一个构造函数或者构造方法的执行,它就能通过return返回一个真正的对象。
    //	所以需要定义一个变量接收方法产生的对象(return返回的)
    var obj = new Object()  --> var obj = {}  // 这俩一样 没有任何区别
    // 属性值很灵活,任意增删改查
    var obj = new Object();
    obj.name = 'abc';
    obj.sex = "male";  // ""和''都是字符串,但是最好使用单引号
    obj.say = function () {  // 在外部以增加属性的的方法增加函数    
    }
    
  2. 自定义

    //	b. 自定义
    function abc() { } // 构造函数和函数在结构上没有任何区别,函数名可以自定义
    // 想通过自己定义的函数构造对象的话,需要借助new操作符才能构造对象。
    var person1 = new person();  // person()函数的执行  有new就会生成对象
    
    // c. 构造函数命名规则 : 大驼峰
    // 大驼峰式命名规则:每个单词首字母都要大写 TheFirstName
    // (小驼峰是第一个单词首字母小写,其他字母大大写) theFirstName
    
  3. 构造函数

    // 方法名和对象名尽量不一样
    // 就好比工厂的制造车过程,定义车的属性
    function Car() {
        this.name = "BMW"; // 定义每个车的名字都是宝马 
        this.height = "1400";  // 宽度
        this.lang = "4900";  // 长度
        this.weight = 1000;    
        this.health = 100;
        this.run = function () {  // 每次run 车的健康值就会减少
            this.health --;
        }
    }
    // 通过同一个构造函数生产出不同的对象,两个对象完全一样,但是彼此独立,可以理解成把Car函数赋值给两个变量了。
    var car = new Car();
    var car1 = new Car();
    // 两个对象是独立的个体,属性值各改各的,互不影响
    car.name = "Maserati";
    car1.name = "Merz";
    
    // 运行函数更改各自的值,也是互不影响
    // 控制台执行
    car.run()  // 执行car对象的run函数,也就是health --
    car.health  //查看car的health就是99
    car1.health  //查看car1的health是100 因为car1没有运行函数 两者互不影响
    
    // 车的颜色可以车主自己选择(传参)
    function Car(color) {
        this.color = color;
        this.name = "BMW"; 
        this.height = "1400";  
        this.lang = "4900";  
        this.weight = 1000;    
        this.health = 100;
        this.run = function () {
            this.health --;
        }
    }
    // 执行函数时把各自的参数穿进去
    var car = new Car('red');
    var car1 = new Car('green');
    
Object.create(原型)方法
function Student(name, age, sex) {  // 自定义需要传参的属性
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.grade = 2022;
}
var student = new Student('zhangsan'18'male');  // 传参
构造函数内部原理

构造函数的基础前提是必须得加new

构造函数隐式三步运算
  1. 在函数体最前面隐式的加上this = {}
  2. 执行this.xxx=xxx;
  3. 隐式的返回this
function Student(name, age, sex) {  
    // 有了new之后  在逻辑最顶端会生成一个var this = {};
    // 产生的AO就会存储这个空对象,传参的属性会存到AO里面的this中
    // AO { this : {name : 'Jason', age : 18, sex : 'male'}}
    // this会被填充满  构造函数中有的属性this都有了 传的参数就是this的属性值
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.grade = 2022;
    // return this;  // 在函数末尾会隐式的return this 生成this对象
}
var student = new Student('Jason'18'male');  // 传参
function Person()(name,height) {
    this.name = name;
    this.height = height;
    this.say = function () {  // 这个方法属于这个对象
        console.log(this.say);  // 这里的this是上级的第一人称 也就是指代this.say
    }
}

new Person();  // 看到new加函数执行 函数内部一定发生隐式三步运算 没new就是正常的函数执行

console.log(new Person('xiaowang',180).name)  // 传参之后打印name 不传参没东西给你打印  只会打印undefined  
// new Person会返回一个对象 这里是直接利用了  没有定义其他变量接收
function Person()(name,height) {  // 一个特殊的构造函数
    var taht = {};   // 定义一个显式的变量用于接收属性和参数
    that.name = name;
    that.height = height;
    return that;  // 显式返回
}

// 模拟系统函数构造方法
var person = new Person('xiaowang',180);  // 可以理解为函数带参数之后赋值给person
var person1 = new Person('xiaozhang',175);  // 可以理解为函数带参数之后赋值给person1
function Person()(name,height) {
    // var this = {};
    this.name = name;
    this.height = height;
    this.say = function () {  
        console.log(this.say);
    }
    return {}; // 如果把下面的隐式返回this改成显式返回空对象会怎样?可以返回数组、对象、函数等,但是不能写原始值(123这种),否则还是默认返回this
    // return this;
}
var person = new Person('xiaowang',180);  // 打印person就会是空对象
var person1 = new Person('xiaozhang',175);  // 打印person1就会是空对象

包装类

属性和方法是对象(对象、数组、函数)特有的东西。

原始值没有方法和属性,是一个独立的个体。

原始值想要赋属性值需要调用包装类

new String();

// str也能像对象一样new一个操作
var str = new String('abcd') // undefined
str.a = 'bcd'  // bcd
str.a  // bcd
str.sayValue = function () {
    returnthis.a
}  // function () {return this.a}
str.sayValue()  // 加括号是执行函数  输出"bcd"
var arr = [1,2,3,4,5]  // 数组本身就有属性length,length不但能访问还能赋值
arr.length  // 5
arr.length = 2  // 数组成[1,2]

// 包装类
var str = "abcd";
str.length = 2;  // 隐式过程 new String('abcd').length = 2; 然后把2返回给str.length 然后删除自己(new String('abcd').length = 2)
console.log(str);  // 这里打印还是原来的str,所以打印结果是abcd,上面的隐式过程只是删除了新建的String('abcd')
console.log(str.length); // 4   注意length是系统自带的属性
// new String('abcd').length

new Boolean();

// undefined和null不可以有属性
undefined.abc = '123'  // 报错
null.abc = '123'  // 报错

var num = new Number(123);
var str = new String('abcd');
var bol = new Boolean('true');

new Number();

var num = 123;  // 123就是原始值数字
var num = new Number(123);  // 这里的123是构造函数的123 是在OA这个对象中的123  然后把这个对象赋值给num 123没有属性名 默认属性名是[[PrimitiveValue]](原始值)

num.abc = 'a'  // 控制台再num对象中增加abc这个属性并赋值a
// 打印num就会有abc和[[PrimitiveValue]]这两个属性

// 但是如果这个对象进行运算 那对象中的123又会恢复成原始值
num * 2  // 246 
// 数字的对象能参与运算,参与完就变成数字了 就不是对象了  字符串和布尔类型也是一样的
// 隐式的中间的环节叫包装类

// 原始值是不可能有属性和方法 但是为什么能调用 是因为包装类
// number没有length属性
var num = 4;
num.len = 3; // 无论赋值还是查找,在原始值调用(num.len)的时候会隐式的发生一个过程
// new Number(4).len = 3;   delete  // 新建一个数字对象new Number(4),让数字对象的len=3  然后把3返回给num.len  然后把自己删除

console.log(num.len);  // 这里打印又访问num.len,也是会新建一个另一个Number
// new Number(4).len   // 但是这里并没有赋值操作 一个对象没有属性值打印是undefined
// 这个Number和num.len = 3的操作中生成的Number是两个不同的Number 

练习

// 练习
var str = "abc";
str += 1;  // abc后面加个1  "abc1"
var test = typeof(str);  // test == "string"
if(test.length == 6) {  // 自己没有length 但是包装类会给它返回length = 6
    test.sign = "typeof的返回结果可能是String"// 原始值想要赋值需要调用包装类
    // 换句话说就是赋值跟没赋一样 这里的隐式过程
    // new String(test).sign = "typeof的返回结果可能是String"
}
console.log(test.sign);  // 打印的时候再new String(test).sign 但是没值  所以打印undefined
// 1.运行test() 和 new test()的结果分别是什么?
var a = 5;
function test() {
    a = 0;
    alert(a);
    alert(this.a);  // 如果不new的话 执行期上下文的this原则上都指向window
    var a;
    alert(a);
}
test()  // 0 5 0
new test()  // 0 undefined 0
// 2. 分析下面的JavaScript代码段:
function employee(name,code) {
    this.name = "wangli";  // 属性值写死了  没有参数
    this.code = "A001";
}
var newemp = new employee("zhangming",'A002');
console.log("雇员姓名:" + newemp.name + "<br>");  // 访问newemp.name的时候还是原来的内容
console.log("雇员代码:" + newemp.code + "<br>");  // 访问newemp.code的时候还是原来的内容
// 输出的结果是(A).(选择一项)

// A. 雇员姓名:wangli  雇员代码:A001
// B. 雇员姓名:zhangming  雇员代码:A002
// C. 雇员姓名:null  雇员代码:null
// D. 代码有错误,无输出结果
//5.闭包+包装类
function Person(name, age, sex) {
    var a = 0;
    this.name = name;
    this.age = age;
    this.sex = sex;
    function sss() {
        a ++;
        console.log(a);
    }
    this.say = sss;
}

var oPerson = new Person();  // 包装类
oPerson.say();  // 1 闭包 子函数共用上级函数中的AO 所以第一次是1 第二次是2
oPerson.say();  // 2
var oPerson1 = new Person();  //产生新的闭包 和上面的互不影响
oPerson1.say();  // 1
// 下面这段js代码执行完毕之后c,y,z的值分别是多少?
// x = 1  y = 4  z = 4   
// 预编译:AO {add:function () {return n = n + 3} } 
// 注意只有一个add函数  只是返回值不一样 后面的add会覆盖前面的add内容 因为AO中只有一个add
var x = 1, y = z =0;
function add(n) {
    return n = n + 1;
}
y = add(x);   // 这里调用的add是预编译完了之后的add AO中存储的是return n = n + 3
function add(n) {
    return n = n + 3;
}
z = add(x);    // 这里调用的add是预编译完了之后的add
arguments是js中函数内置的一个对象,而执行函数方法的实参中值都存储在arguments中

// 下面代码中console.log的结果是[1,2,3,4,5]的选项的是:A、C
// A
function foo(x) {
    console.log(arguments)
    return x
}
foo(1,2,3,4,5)

// B  没有函数调用 不报错也不执行
function foo(x) {
    console.log(arguments)
    return x
}(1,2,3,4,5)

// C  立即执行函数 
(function foo(x) {
    console.log(arguments)
    return x
})(1,2,3,4,5)
// 请问以下表达式的结果是什么?
// parseInt(string, radix)接收两个参数,第一个参数是待转换的字符串,第二个参数是范围在2-36中的一个整数,表示几进制,作为基底。例:parseInt(3,8)就是把3以八进制为基底转换成十进制
parseInt(3,8)  // 3  3当成八进制的数还是3
parseInt(3,3)  // NaN  3当成3进制的数是10 所以不能把3当成3进制数
parseInt(3,2)  // NaN  3当成2进制的数是11 所以不能把3当成2进制数
parseInt(3,0)  // 3、  写0跟没写一样  会把原来的数返回
// 以下哪些是javascript语言typeof可能返回的结果
A. string  // 可
B. array   // 不可 array返回function 但没有返回array的
C. object  // 可 object返回function
D. null    // 不可 历史遗留问题  null返回object 但没有返回null的
// 看看下面alert的结果是什么 考点是a=10和arguments[2] = 10 是不是互相映射 一个改另一个也改
function b(x, y, a) {
    arguments[2] = 10;  // a一开始参数时3 但是这里又把10赋值给a了
    alert(a);  // 10  alert是弹出框
}
b(1, 2, 3);
// 如果函数体改成下面,结果又会是什么?
a = 10;
alert(arguments[2]);  // 10

function test(x, y, a) {
    argument[2] = 10;  // argument[2] = 10 ==> a = 10
    console.log(a);
}
test(1, 2, 3)

作业

// 8.写一个方法,求一个字符串的字节长度。(提示:字符串有一个方法charCodeAt();一个中文占两个字节,一个英文占一个字节.
// 定义和用法
// charCodeAt()方法可返回指定位置的字符的Unicode编码。这个返回值是0-65535之间的整数。(当返回值是<=255时为英文,当返回值>255时为中文)
// 语法
stringObject.charCodeAt(index)
eg:
<script type="javascript/ text">
var str="Hcllo world!"
console.log(str.charCodcAt(l));//输出101
</script>

// 解答
// 方法一:都默认是占一个字节,然后遇到中文再加1
// 1. 当前字符位的unicode > 255 , 那么该字符字节长度为2
// 2. <= 255 为1
var str = "abda张杰真帅hdaj"
function bytesLength(str) {
    var count = str.length;
    for(var i = 0, i < str.length, i ++)
    if (str.charCodcAt(i) > 255) { // 判断每位i的字符串长度
        count ++;
    }
    return count;
}
// 方法二:判断是大于255还是小于255然后再进行判断
var str = "abda张杰真帅hdaj"
function bytesLength(str) {
    var count = 0;
    for(var i = 0, i < str.length, i ++)
    if (str.charCodcAt(i) > 255) { // 判断每位i的字符串长度
        count += 2;
    }else {
        count ++;
    }
    return count;
}
// 方法二:判断是大于255还是小于255然后再进行判断
var str = "abda张杰真帅hdaj"
function bytesLength(str) {
    var count = 0;
    for(var i = 0, i < str.length, i ++)
    if (str.charCodcAt(i) > 255) { // 判断每位i的字符串长度
        count += 2;
    }else {
        count ++;
    }
    return count;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好好学习_fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值