下载安装运行环境:https://nodejs.cn/download/
编写helloworld,node.js:
console.log("Helloworld");
执行,在对应的目录下执行命令行
node ./main.js
变量
变量可以分为基本数据类型以及复制数据类型
基本数据类型直接存,复制数据类型存的是引用
基本数据类型:整数,小数,逻辑变量
console.log(1); // 整数
console.log(1.2); // 小数
console.log(true); // 逻辑true
console.log(false); // 逻辑false
var a; // 分配一个内存,基本数据,
a = 3.5;
console.log(a);
a = 4;
console.log(a);
a = true;
console.log(a);
var b = null; // 没有存放任何数据
console.log(b);
// 使用一个没有初始化的变量, undefine
var c;
console.log(c);
// 按照顺序存放一组元素,从0开始,1, 2, 。。。
// [], 定义了一个数组对象
c = [];
console.log(c);
c = [1, 2, 3, 4]
console.log(c);
// 数组是根据索引来访问元素, 索引是从0开始的, 索引-->value
console.log(c[0]); // 第0个元素 1
console.log(c[1]); // 第1个元素 2
console.log(c[2]); // 第2个元素 3
console.log(c[3]); // 第3个元素 4
// 数组里面可以存放任何不同类型的元素
c = [1, 2.1, true, false, [0, 1, 2]];
// {}表示定义一个表,字典, key: -->value
var list_table = {};
list_table = {
0: true,
hello: 3,
}
// 访问已经存在的key --> value,
console.log(list_table.hello);
console.log(list_table["hello"]);
console.log(list_table["0"]);
list_table["blake"] = 33;
console.log(list_table);
// 定义一个变量,让它指向一个函数对象
// function关键字, (参数1, 参数2) { 函数体}
var call_func = function (param1, param2) {
console.log("Hello call func!!!!", param1, param2);
return;
}
// 变量,或者是名称, 传递参数
call_func(3, 4);
// 函数的返回值,可以有返回值,可以没有返回值
call_func = function(param1) {
return (param1); // 返回我们的数据
};
// 在外面可以使用变量来接收这个数据
var ret = call_func(4);
console.log(ret);
// 函数名称来定义一个函数,调用的时候可以使用函数名称
// 这个函数名称就是指的这个函数对象
// 这个函数名称,整个js文件里面有效果
// 函数定义,但不会执行,真正执行的是调用,
// 调用的时候,再跳到函数里面执行,执行完成后,在返回到调用函数的下一条指令,继续执行
function test_func_name() {
console.log("test_func_name");
}
// 函数调用
console.log("begin call func");
test_func_name();
console.log("out call func");
// 字符串对象; "Hello", 'Hello'
var hello_str = "Blake";
console.log(hello_str);
hello_str = 'Blake';
console.log(hello_str);
// 整数,小数,逻辑变量, --->简单的数据对象, = 传的是值
// 字符串对象, 数组对象,表, 函数对象 = 传递的是引用, 变量"指向"哪个对象;
var b = 3;
var c = b; // 传递的是值,因为变量本身的内存就能存下基本数据类型;
c = 4;
console.log(b); // b = 3
// 复杂数据对象,我们变量里面存放的是引用,引用是可以直接存放到我们的变量所对应的内存里面的;
b = [1, 2, 3]; // 把数组的访问快捷方式,"引用"复制给变量b的内存
c = b; // 传递的不是值,而是引用,对象的地址,对象的快捷方式
c[0] = 2; // c[2, 2, 3]
console.log(b); // [1, 2, 3] ? [2, 2, 3]
// 变量保存了基本数据类型的值
// 变量保存了复杂数据对象的引用,----> 变量指向了这个复杂的数据对象,"访问的快捷方式", "对象所在的地址"
var System = {
test_name: function() {
console.log("test_name func");
},
test_func: function() {
console.log("test_func func");
},
age: 10,
sex: -1,
name: "Blake",
};
// System变量 ---> 表对象,表对象有两个元素key, value
// 表.key-->value
System.test_name();
System.test_func();
console.log(System.name);
var Cmd = [
function() {
var my_test = 10;
console.log("helloworld");
},
];
Cmd[0]();
// 函数重名,是我们很多错误的根源
var my_func = function() {};
/*
function test_func_call() {
console.log("test_func_call");
}*/
test_func_call(); // 为什么在这里调用,调用的不是上一个的函数呢??
// 定义两个重名的函数
function test_func_call() {
console.log("test_func_call copy");
}
// null, 主动,undefine, // 被动
test_func_call();
var undefine_temp;
console.log(undefine_temp);
var a_ptr = {
0: "Blake"
};
var b_ptr = {
0: "Huangdong",
};
a_ptr = b_ptr;
模块
1:js里面代码可以放在不同的文件里,称为代码模块;
2:一个模块需要引用其它模块代码的时候使用 require;
3: require:
(1) 如果是第一次调用,那么就加载,执行脚本,返回module.exports;
(2)如果不是第一次执行,那么直接返回module.exports,不执行脚本;
utils.js:
var utils = {
random_int: function (start, end) {
var num = start + (end - start) * Math.random();
num = Math.floor(num);
return num;
},
};
module.exports = utils;
main.js
注意this的机制和bind的强制绑定
// 返回的是utils里面的module.exports
// 第一次执行,加载utils.js文件,然后并执行这个文件里面的js指令,返回module.exports;
// 如果不是第一次,直接返回module.export
// 指向的是module.exports指向的对象
var utils = require("./utils");
console.log(utils);
var num = utils.random_int(10, 20);
console.log(num);
// this = ?
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);
// this 有什么用呢?
面向对象
- 注意new的机制其实是调用构造函数构造了一个表
- 每个函数都有prototype,这个prototype相当于一个元表,构造出来新表后拥有旧表的全部功能。prototype会被复制到新表的__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); var p2 = new person("xiaotian", 12); console.log(p2); p.test_func(); p2.test_func(); // new prototype // 每一个函数对象,都会有一个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__里面搜索; // 定义个类 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());
继承
- 需要定义一个新的funcion
- 用basefunction.Call(this)来继承数据成员
- 用funcion.prototype来继承成员函数
- 如果想要调用子类的函数func 可以用basefunction.prototype.func.call(this)
通用继承方法Class的编写// 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){ params.extend.call(this); } if(params.init){ params.init.call(this); } }; // 继承基类的方法 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);