【ECMAScript】构造函数原理、实例化原理、包装类

1. 构造函数

new 做了什么:把 this 造出来,改变 this 指向,指向实例化对象

GO = {
  Car: (function),
  car1: {
    color: 'red',
    brand: 'Benz'
  }
}
AO = {
  // this: {}, // 1. 执行到new,在AO里保存一个空的this对象
  this: {		  	// 2. 保存值到 this 对象
    color: color, 
    brand: brand
  }
  
}

function Car(color, brand) {
  // 当被实例化时,产生AO,自动保存this为对象
  // this = {color: color, brand: brand} 
  this.color = color;
  this.brand = brand;
  // return this;  // 3. 隐式的 return this
}

// 当 Car 被实例化时,就相当于普通函数被执行的时候,这个时候 Car 也有 AO

// new Car的时候把返回的this交给了car1,所以说最终还是保存到GO中了
var car1 = new Car('red', 'Benz'); // 这里返回的是 this,所以 this 就是 car1
console.log(car1.color);

不用构造函数实现同一件事

function Car(color, brand) {
  var me = {};
  me.color = color;
  me.brand = brand;
  return me;
}

var car = new Car('red', 'Mazda');
console.log(car.color);
console.log(car.brand);

和普通函数没区别,new的时候只是系统帮忙把this指向实例化的对象

function test(){
  var obj = {
    name: 'Tom',
    color: 'blue'
  }
  return obj;
}
var obj = test();
console.log(obj.name);

当构造函数返回的是引用值时,如:函数、对象、数组,就返回引用值

返回的是原始值,没有任何作用

function Car(){
  this.color = 'red';
  this.brand = 'Benz';
  return {};
}

var car = new Car();
console.log(car.color);

2. 包装类

原始值并没有自己的方法和属性,所以没有a.属性

var a = 1;
var b = 'abc';

问:数字是不是一定是原始值?

答:不一定,还可以通过 new Number() 将其变为对象

var a = 1;
console.log(a);
var b = new Number(a); // 经过 new 之后,就实例化了一个对象,数字对象
console.log(b); // 对象
// 成为对象之后就可以给其设置属性和方法
b.len = 1;
console.log(b);

// 经过 new 包装之后,再参与运算,又恢复到了初始值
var d = b + 1; // 2 

var aa = new Number(1);
console.log(aa); // 对象

var bb = aa + 1;
console.log(bb); // 2
console.log(aa); // 对象

new Number, new String, new Boolean

var test = new Number(undefined); // NaN
var test = new Number(null); // 0

var test = new String(undefined); // 'undefined'

// null 和 undefined 不可以设置任何的属性和方法
null.length;  // 报错
undefined.length; // 报错

包装类案例⭐

// JS 包装类
var a = 123; // 原始值 -> 数字   原始值没有方法和属性
a.len = 3;	// 但若非要相加,系统就会给你变成数字对象 new Number(123)
// new Number(123).len = 3; 赋值完之后new Number(123)这个值并没有地方保存 -> 所以删除了 delete
// 赋值之后没地方保存,就删除了

console.log(a.len); // undefined ⭐

问:那么如何能够把 a.len 保存起来

var a = new Number(123);
a.len = 3;
console.log(a.len); // 3

问:原始值没有方法和属性,为什么str.length可以打印出来⭐

// 原始值没有方法和属性,为什么str.length可以打印出来
var str = 'abc';
str.length; // 3

系统内部 new String(str).length;
通过包装类访问到new String 独有的属性,这个时候不需要保存

数组可以被length属性截断

var arr = [1, 2, 3, 4, 5];
// 数组的截断方法
arr.length = 3; // 赋值为几,就数几位留下来,后面的全部删除
arr; // [1, 2, 3];

arr.length = 6; // 多的部分会填 empty

字符串

var str = 'abc';
str.length = 1; // 系统会做 new String(str).length = 1;临时容器,没地方保存,delete
console.log(str); // 'abc'

console.log(str.length); // 3  这时候重新包装 new String(str).length

3. 面试题

  1. 打印结果是什么?⭐

    var name = 'languiji';
    name += 10; // 'languiji10'
    
    var type = typeof(name); // 'string'
    
    if(type.length === 6){ // true
      type.text = 'string'; // new String(type).text = 'string'; ->delete
    }
    
    console.log(type.text); // undefined
    
    如果想要输出type.text,则
    var type = new String(typeof(name));
    
  2. 打印结果是什么?

    function Car(brand, color){
      this.brand = 'Benz';
      this.color = 'red';
    }
    
    var car = new Car('Mazda', 'blank');
    console.log(car); // {brand: 'Benz', color: 'red'}
    
  3. 执行结果?

    function Test(a, b, c) {
      var d = 1;
      this.a = a;
      this.b = b;
      this.c = c;
      
      function f(){
        d++;
        console.log(d);
      }
      this.g = f;
      // 隐式 return this; -> 闭包
    }
    
    var test1 = new Test();
    test1.g(); // 2
    test1.g(); // 3
    
    var test2 = new Test();
    test2.g(); // 2
    
    
  4. 打印结果是什么?

    var x = 1,
        y = z = 0;
    
    function add(n){
      return n = n + 1;
    }
    
    y = add(x);
    
    function add(n){
      return n = n + 3;
    }
    
    z = add(x);
    
    console.log(x, y, z); // 1 4 4
    
    GO = {
      x: 1,
      y: 0 -> 4,
      z: 0 -> 4,
      add: function add(n){return n = n + 3;}
    }
    
  5. 以下三个函数哪一个能够输出1,2,3,4,5

    function foo1(x) {
      console.log(arguments);
      return x;
    }
    foo1(1, 2, 3, 4, 5);
    
    function foo2(x) {
      console.log(arguments);
      return x;
    }(1, 2, 3, 4, 5)
    
    (function foo3(x) {
      console.log(arguments);
      return x;
    })(1, 2, 3, 4, 5)
    
    // 答:foo1, foo3
    
  6. 打印结果是什么?

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

4. ASCII码

表1:0 - 127

表2:128 - 255

ASCII码中的字符长度都是一个字节 byte

UNICODE 码 涵盖 ASCII码 :0-255为ASCII码,255之后为两个字节

var str = 'a';
var pos = str.charCodeAt(0); // 打印字符在UNICODE中是第几位
console.log(pos); // 97

5. 作业

写一个函数,接收任意一个字符串,算出这个字符串的总字节数

// 方法1
function compute(str) {
  var total = 0;
  for(var i = 0; i < str.length; i++) {
    var pos = str.charCodeAt(i);
    if(pos >= 0 && pos <= 255) {
      total += 1;
    } else {
      total += 2;
    }
  }
  return total;
}
console.log(compute('hello 中文!'));


// 方法2
function getBytes(str){
  var bytes = str.length; // 字符串长度
  for(var i = 0; i < str.length; i++) {
    var pos = str.charCodeAt(i);
    if(pos > 255){ // 如果是中文字符,bytes+1
      bytes++;
    }
  }
  return bytes;
}
console.log(compute('hello 中文!'));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值