一、代码模块
1、js里面代码可以放在不同的文件里,称为代码模块;
2、一个模块需要引用其它模块代码的时候使用 require;
3、 require:
(1) 如果是第一次调用,那么就加载,执行脚本;
(2) 每个代码模块由module.exports 导出的对象;
(3) 每次require的时候,都返回module.exports;
(4)如果不是第一次执行,那么直接返回module.exports;
utils.js
//定义一个表utils,表内定义一个函数random_int
var utils = {
random_int: function (start, end) {
var num = start + (end - start) * Math.random();
num = Math.floor(num);
return num;
},
};
module.exports = utils; //导出表utils,也可以直接到导出表中的函数
main.js
var utils = require("./utils");
console.log(utils);
var num = utils.random_int(10, 20);
console.log(num);
二、this
1、function.call(this, param1, param2);
2、表.函数名(参数):
(1) 函数里面有一个this对象,指的是外面的表;
(2) 如果外面没有表,那么this为undefine;
(3) 函数.bind(数据对象),会产生一个新的函数对象,调用该函数的this,就是外面bind的对象;
function test_func(name, sex) {
this.name = name;
this.sex = sex;
}
// this, 类是与一个参数一样的,显式传递this
// 函数对象.call(实例, 参数)
var xiaoming = {};
test_func.call(xiaoming, "xiaoming", 10);
console.log(xiaoming);
// 隐式传递this
var xiaohong = {
name: "xiaohong",
test_func: function() {
console.log(this);
},
test_bind: function() {
console.log(this);
}.bind(4),
};
// 隐式的传递this,将xiaohong 作为this,传给该函数。
xiaohong.test_func();
xiaohong.test_bind();
// 强制传递this;
var func = function() {
console.log(this);
}.bind(xiaohong);
func();
func = function() {
console.log(this);
}
// bind是在原来的对象的基础上,产生了一个新的函数对象;强制bind this,优先级额比其它的都高;
func = func.bind(xiaohong);
func();
func.call(4);
// 强制bind > 显示 > 隐式
xiaohong.test_func.call(4);
三、new与构造函数
1、js 构造函数: 函数(参数),一般和类名一样;
2、new +构造(参数1, 参数2….);
(1)先创建一个{}对象;
(2)将这个新对象绑定到函数里面的this;
(3)构造函数对象的prototype 复制给新对象的 proto
(4) 返回新创建的对象;
3、表.函数调用搜索顺序,现在key, value里查找,再到proto里找;
function person(name, age) {
this.name = name;
this.age = age;
}
person.prototype.test_func = function() {
console.log("person test_func called!!!!");
console.log(this);
};
var p = new person("xiaohong", 10);
console.log(p);
p.test_func();
运行结果:
person { name: ‘xiaohong’, age: 10 }
person test_func called!!!!
person { name: ‘xiaohong’, age: 10 }
四、原型引用
1:每个函数对象都有prototype属性;
3: clone一个函数对象的prototype;
(1)定义一个空函数;
(2)空函数的prototype = 函数对象的prototype;
(3) 新构造函数.prototype = new 空函数();
// 每一个函数对象都有一个prototype变量,指向一个对象,
// 什么也没有就为{}
var func_temp = function() {
console.log("func_temp####");
};
console.log(func_temp.prototype);
// end
// prototype是一个对象,所以可以扩充key: value;
func_temp.prototype.test_func = function() {
console.log("test_func", this);
};
func_temp.prototype.test_func2 = function() {};
// step1 var a = {};
// step2 a __proto__: prototype 的浅复制;
// step3 实例 作为this,传递给后面的函数
// step4 调用这个函数;
var data = new func_temp();
// 两个表,但是里面的值一样;
console.log(data.__proto__);
console.log(func_temp.prototype);
// data is 表;
data.name = "XXXXXX"
data.__proto__.test_func();
// 把data, 作为this,传递给 data.__proto__对象里面的函数;
data.test_func(); // ---> data.__proto__.test_func.call(data);
data.__proto__.test_func.call(data);
data.test_func = function() {
console.log("new test_func", this);
}
data.test_func();
// data.key_func, 首先会在实例的表里面搜索,有没有这样的key,如果没有,那么再到对象的__proto__里面搜索;
五、js实现继承
1、子类clone 基类构造函数的prototype;
2、子类和基类如果有同名的方法,会现在当前这个类的函数;
3、子类的实例显示的调用基类的函数
基类.prototype.函数名字.call(实例, 参数1,参数2);
4、编写一个Class()方法来定义一个类,让它继承基类;
// 定义个类
function Point() {
this.xpos = 0;
this.ypos = 0;
}
Point.prototype.set_pos = function(x, y) {
this.xpos = x;
this.ypos = y;
}
Point.prototype.get_ypos = function() {
return this.ypos;
}
// end
var p1 = new Point();
var p2 = new Point();
p1.set_pos(10, 10);
p2.set_pos(100, 100);
console.log(p1.get_ypos());
console.log(p2.get_ypos());
// js 继承
var Person = function() {};
Person.prototype.set_name = function(name) {
this.name = name;
console.log("set_name called");
};
Person.prototype.set_age = function(age) {
this.age = age;
};
Person.prototype.test_func = function() {
console.log("person test_func");
};
// 定义一个人;
var Man = function() {};
// Man.prototype();
// 做法(1)
// Man.prototype = Person.prototype; // ?可以吗?
// 在原来的基类的prototype做一次浅拷贝
var Super = function() {};
Super.prototype = Person.prototype;
Man.prototype = new Super();
Man.prototype.set_sex = function(sex) {
this.sex = sex;
};
Man.prototype.test_func = function() {
Person.prototype.test_func.call(this);
console.log("Man test_func");
}
var m = new Man();
m.set_name("xiaoming");
m.set_age(10);
m.set_sex(0);
console.log(m);
m.test_func();
// end
function Class(params) {
var new_class = function() {};
// 继承基类的方法
if (params.extend) {
var Super = function() {};
Super.prototype = params.extend.prototype;
new_class.prototype = new Super();
}
for(var key in params) {
if (key == "extend") {
continue;
}
new_class.prototype[key] = params[key];
}
return new_class;
}
var Student = Class({
extend: Person,
set_class: function(class_num) {
this.class_num = class_num;
},
set_grade: function(grade) {
this.grade = grade;
}
});
var s = new Student();
s.set_name("xiaohong");
s.set_class(10);
s.set_grade(2);
console.log(s);