1. 函数实例化原理
1.1 构造函数中的this
- this指向的不是构造函数本身
- 当构造函数实例化的时候,AO生成 就已经生成了this
- new实例化了对象之后,this指向的是这个实例化的对象,在没有实例化之前,指向的window ```javascript // 在没有实例化之前,指向的是window,new实例化之后,this指向的是这个实例化的对象 function Car(color, brand){ this.color = color; this.brand = brand; console.log(this); }
Car(); var c1 = new Car(‘red’, ‘mazda’); // 第一次输出 window // 第二次输出 Car{}
// 上述实例化理解 function Car(color, brand){ this.color = color; this.brand = brand; // var this ={ // color: color, // brand: brand, // } // 隐式增加了return this }
// 不用new 直接指向函数 function Car(color, brand){ var obj = {} obj.color = color; obj.brand = brand;
return obj }
var car = Car(‘red’, ‘audi’); console.log(car);
<a name="eLJoq"></a>
## 1.2 构造函数中的return
- number, string, undefined, boolean, null等原始值,会被忽略,结果还是return this
- [], {}, function(){},等引用值,会改变返回引用值
```javascript
function Car(){
return null // undefined, string boolean, number
}
var car = new Car();
console.log(car); // Car {}
function Car(color){
this.color = color;
return [] // {} function(){}
}
var car = new Car();
console.log(car); // [], {}, function(){}
console.log(car.color); // undefined
2. 包装类
2.1 new Number 转换为数字对象
var a = 1;
console.log(a); // 1 原始值
var b = new Number(a);// 数子对象 => 实例化对象后的数字
console.log(b); // Number{1}
b.len = 1;
b.add = function(){
console.log(1);
}
console.log(b);// Number {1, len: 1, add: f()}
var d = b + 1;
console.log(d);// 2 此时的运算使得b又变成了一个原始值
console.log(b);// Number {1, len: 1, add: f()} 参与运算之后,又成了数字对象
2.2 new string 转换为字符串对象
var a = 'abc';
console.log(a); // abc
var aa = new String('abc');
aa.name = 'aa';
console.log(aa);// {'abc', name:'abc'}
var bb = aa + 'bcd';
console.log(bb);// 'abcbcd'
console.log(aa); // {'abc', name:'abc'}
2.3 JS包装类过程
2.3.1 原始值并没有自己的属性和方法
给原始值添加属性和方法, 系统会包装类进行添加, 但是没有提供变量用于保存, 系统会默认delete
// 原始值并没有自己方法和属性
var a = 123;
a.len = 3;
// a是原始值,不能添加属性
// new Number(a).len = 3;
// delete new Number()
cosnole.log(a.len);
var str = 'abc';
// new String(str).length -> str经过了包装类
console.log(str.length);// 3
2.3.2 数组截断
数组可以被length 进行截断
// 数组的截断
var arr = [1, 3, 4, 5, 6];
arr.length = 3;
console.log(arr); // [1, 3 ,4]
arr.length = 6;
// arr -> [1, 3, 4, 5, 6, empty]
// arr[6] => undefined
// 字符串的截断?
var str = 'abc';
str.length = 1;
// new String(str).length = 1 -> delete
console.log(str);// abc
// 再次new String(str).length
concole.log(str.length);// 3
3.案例
案例1
var name1 = 'languiji';
name1 += 10; // name1 => 'languiji10'
var type = typeof(name1);// 'string'
if(type.length === 6){
type.text = 'string';
// new String(type).text = 'string'
// delete
}
console.log(type.text); // undefined
案例2
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;
}
var t1 = new Test();
t1.g(); // 2
t1.g(); // 3
var t2 = new Test();
t2.g(); // 2
案例3
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
案例4
// 函数1
function foo1(){
console.log(arguments);
return x;
}
foo1(1, 2, 3, 4, 5);
// 函数2
function foo2(x){
console.log(arguments);
return x
}(1, 2, 3, 4 ,5)
// 函数3
(function foo3(x){
console.log(arguments);
return x
})(1, 2, 3, 4, 5)
以上那个函数可以输出 1, 2, 3, 4, 5
1.3可以
2 => (1, 2, 3, 4, 5)被当做表达式,不会被执行
案例5
// 当非严格模式下中的函数没有包含 *剩余参数,默认参数,解构赋值,那么arguments对象中的值会跟踪参数的值
function b(x, y, a){
// a = 10;
// console.log(arguments[2]); // 10
arguments[2] = 10;
console.log(a); // 10
}
b(1, 2, 3);
严格模式下不会跟踪参数的值
'use strict'
function b(x, y, a){
arguments[2] = 10;
console.log(a); // 3
}
b(1, 2, 3);
4.练习
写一个函数,接受任意一个字符串,算出这个字符串的总字节数
// ASCII 码 表1 0- 127, 表2 128-255
// 一个字节
// UNICODE码 -> 涵盖ASCII码 2个字节
function bytes(str){
var allBytes = 0;
for(var i = 0; i < str.length; i++){
var code = str.charCodeAt(i);
if(code <= 256){
allBytes += 1;
}else{
allBytes += 2;
}
}
console.log(allBytes);
}
bytes('你好,中国! hello!');
function getBytes(str){
var Bytes = str.length;
for(var i = 0; i < str.length; i++){
var codeIndex = str.charCodeAt(i);
if(codeIndex > 255){
Bytes++;
}
}
return Bytes;
}