求一个字符串的字节长度
注意点:汉字的字节长度是两个
// 求一个字符串字节长度(汉字是两个字节)
function bytesLength(str) {
var count = 0;
for(var i=0; i<str.length;i++) {
if(str.charCodeAt(i) > 255) {
count += 2;
}else {
count ++;
}
}
return count;
}
原型
定义: 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象可以继承该原型的属性和方法 (原型也是对象)
可以利用原型的特点和概念,可以提取共有属性
proto&构造函数&new(object)
//Person的对象-原型对象
Person.prototype.name = "abc";
//构造函数 Person
function Person() {
// var this = {
// _proto_: Person.prototype
//}
}
var person = new Person();
在new person时 发生:
this -> _proto:Person.prototype()-原型对象 可以person可以调用原型中的属性和方法 person.proto = obj(可以被修改-之后就会继承obj的内容)
插入一个小问题:代码
Person.prototype.name = "sunny";
function Person() {
// var this = {
// _proto_: Person.prototype
//}
}
var person = new Person();
Person.prototype = {
name:"cherry"
}
console.log(person.name) // sunny
原因(对象空间的引用或者指向)
- person.name -> this.proto(Person.prototype原型)上的name属性
- Person.prototype -> 一个对象空间 -> {name:"sunny"}
- person.name -> this.proto -> 一个对象空间 -> {name:"sunny"}
- 修改指向引用 Person.prototype -> 一个对象空间 -> {name:"cherry"} 5.由于person.name 先new -> this.proto -> 的指向空间没有变 -> {name:'sunny'} 所以:person.name = 'sunny'
如果纯粹修改Person.prototype.name = "cherry"; 则person.name = 'cherry'
原型连
概念:new对象沿着作用域链去查找属性和方法的 链 引出:

// 如果要求打印出son.lastName
son this._porto_: Son.prototype
father this._porto_: Father.prototype
grand this._porto_: Object
由于 son this._porto_ -> father this._porto_ -> father grand._porto_ -> {lastName,Object.prototype} 所以son.lastName 顺这链找到了grand.lastName = "Deng"
console.log(son.lastName) // "Deng"
Object.create()
创建对象 Object.create(原型) 创建对象、指定原型
var obj = { name:'sunny'}
var obj1 = Object.create(obj)
// obj1 = {} 并且obj1的原型是obj obj1.name= "sunny"
不是所有对象都是继承自Object Object.create(null)是特例
判断类型
Object.prototype.toString.call(123)
"[object Number]"
call/apply
作用: 改变this指向 区别: 后面传的参数形式不同
- 改变this指向1
function Person(name, age) {
// Person.call() 会将this -> obj
this.name = name;
this.age = age;
}
var person = new Person("deng", 100)
var obj = {};
Person.call(obj, "cheng",300) //改变this指向 借用方法
- 改变this指向2
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
// var this = Student
Person.call(this, name, age, sex); //Student则有了Person的属性
this.tel = tel;
this.grade = grade;
}
var student = new Student('sunny',123,'male',139,2017)
student -> {name: "sunny", age: 123, sex: "male", tel: 139, grade: 2017}
- call/apply传参形式不同 Person.apply(obj, ["cheng",300]) Person.call(this, [name, age, sex]);
继承那点方式
-
传统的形式-> 原型链
过多的继承了没有用的属性
// Animal构造函数 function Animal(){ } // Animal原型山添加一个属性species Animal.prototype.species = "动物"; // 将Cat的prototype对象指向Animal的prototype对象 Cat.prototype = Animal.prototype; // 原型的修改会导致Cat的构造器的修改,所以需要将cat的构造器重新指向Cat它自己 function Cat(){ } Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); // cat的对象中就有了species这个属性 alert(cat1.species); // 动物 -
借用构造函数(call/apply)
不能继承借用构造函数的原型 每次构造函数都要多走apply/call函数
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } function Student(name, age, sex, tel, grade) { // var this = Student Person.call(this, name, age, sex); //Student则有了Person的属性 用apply也行 this.tel = tel; this.grade = grade; } var student = new Student(); -
共享原型(多个构造函数共用一个原型)
一个原型修改另一个也在修改
// 标准方法 function inherit(Target, Origin) { Target.prototype = Origin.prototype; } -
圣杯模式(完善)
function Father() {} function Son() {} function F() {} // 中间层 F.prototype = Father.prototype; // son就形成了继承 Son.prototype = new F(); //如果一个修改这样不会影响另一个(因为new F是独立存在的一个空间)标准方法:
function inherit(Target, Origin) { function F() {}; F.prototype = Origin.prototype; Target.prototype = new F(); // 构造器重新修改过来 Target.prototype.constructor = Target; // 继承自谁(保存值) Target.uber = Origin.prototype; }高级写法(一般是库写法)
私有化属性(形成了闭包,变量引用与保留了inherit() 上下文)
var inherit = (function () { var F = function() {} return function (Target, Origin) { F.prototype = Origin.prototype; Target.prototype = new F(); // 构造器重新修改过来 Target.prototype.constructor = Target; // 继承自谁(保存值) Target.uber = Origin.prototype; } }()) -
深拷贝继续(数组和对象)
function deepCopy(p, c) {    var c = c || {};    for (var i in p) {      if (typeof p[i] === 'object') {        c[i] = (p[i].constructor === Array) ? [] : {};        deepCopy(p[i], c[i]);      } else {         c[i] = p[i];      }    }    return c; }